为什么当我试图解除它时,我的Haskell do-notation会打破? [英] Why does my Haskell do-notation break when I try to desugar it?
问题描述
下面的代码来自 99个Haskell问题中的第26个问题 :
组合:: Int - > [a] - > [[a]]
组合0 _ =返回[]
组合n xs = do y:xs'< - tails xs
ys < - combination(n-1)xs'
return(y:ys)
以上代码按预期工作。下面是我的主要功能和打印结果:
main =打印$组合2abcd
- 打印:[ab,ac,ad,bc,bd,cd]
作为学习练习,我尝试解除注释,如下所示:
组合:: Int - > [a] - > [[a]]
组合0 _ =返回[]
组合n xs = tails xs>> = \(y:xs') - >
do
ys< - 组合(n-1)xs'
返回(y:ys)
编译时,运行时出现以下错误:
pre $ PatternMatchFail:/ home / ... / test.hs:(46,34) - (49,37):lambda中的非穷举模式
这里发生了什么?我该如何用>> =
和>>
?
从 Haskell Wikibook :
...带有lambdas的片段与do块大致等价。它不是一个精确的翻译,因为这个符号添加了对模式匹配失败的特殊处理。
考虑这个例子:
f xs = do
(x:_)< - 只需xs
返回x
g xs = Just xs>> =
\(x:_) - >返回x
对于任何非空列表,这些函数是相同的。但是 f []
返回 Nothing
和 g []
返回一个很像你所得到的错误。
这是因为 do
符号处理失败的方式不同。 Monad
typeclass具有失败
函数。您正在使用列表monad,通过返回一个空列表失败。 Maybe
monad通过返回 Nothing
来实现它。无论采用哪种方式, do
表示法中的模式匹配失败都由此函数处理,因此是差异。
正确的翻译方式是:
g xs = Just xs>> =
\xs ' - > $ x $ b(x:_) - >的情况x' return x
[] - >失败一些错误
I have the following code from Problem 26 of the 99 Haskell problems:
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = return []
combinations n xs = do y:xs' <- tails xs
ys <- combinations (n-1) xs'
return (y:ys)
The above code works as expected. Below is my main function and the printed results:
main = print $ combinations 2 "abcd"
-- Prints: ["ab","ac","ad","bc","bd","cd"]
As a learning exercise I tried to "desugar" the do-notation like so:
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = return []
combinations n xs = tails xs >>= \(y:xs') ->
do
ys <- combinations (n-1) xs'
return (y:ys)
This compiles, but gives the following error at runtime:
PatternMatchFail: /home/.../test.hs:(46,34)-(49,37): Non-exhaustive patterns in lambda
What is going on here? How can I replace the do-notation with >>=
and >>
?
From the Haskell Wikibook:
... the snippet with lambdas was "broadly equivalent" to the do block. It is not an exact translation because the do notation adds special handling of pattern match failures.
Consider this example:
f xs = do
(x:_) <- Just xs
return x
g xs = Just xs >>=
\(x:_) -> return x
For any non-empty list, these functions are identical. But f []
returns Nothing
, and g []
returns an error much like the one you're getting.
This is because the do
notation handles failure differently. The Monad
typeclass has a fail
function. You're using the list monad, which fails by returning an empty list. The Maybe
monad implement it by returning Nothing
. Either way, the pattern match failure inside the do
notation is handled with this function, hence the difference.
So the correct way to translate it would be:
g xs = Just xs >>=
\xs' -> case xs' of
(x:_) -> return x
[] -> fail "some error"
这篇关于为什么当我试图解除它时,我的Haskell do-notation会打破?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!