[英]Why does my Haskell do-notation break when I try to desugar it?
我有来自99个Haskell问题的问题26的以下代码:
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = return []
combinations n xs = do y:xs' <- tails xs
ys <- combinations (n-1) xs'
return (y:ys)
上面的代码按预期工作。 以下是我的主要功能和打印结果:
main = print $ combinations 2 "abcd"
-- Prints: ["ab","ac","ad","bc","bd","cd"]
作为一个学习练习,我试图“desugar”这样的记号 :
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = return []
combinations n xs = tails xs >>= \(y:xs') ->
do
ys <- combinations (n-1) xs'
return (y:ys)
这会编译,但在运行时会出现以下错误:
PatternMatchFail: /home/.../test.hs:(46,34)-(49,37): Non-exhaustive patterns in lambda
这里发生了什么? 如何用>>=
和>>
替换do-notation?
来自Haskell Wikibook :
......与lambdas的片段与do块“大致相同”。 它不是一个精确的转换,因为符号添加了模式匹配失败的特殊处理。
考虑这个例子:
f xs = do
(x:_) <- Just xs
return x
g xs = Just xs >>=
\(x:_) -> return x
对于任何非空列表,这些功能都是相同的。 但是f []
返回Nothing
,而g []
返回的错误很像你得到的错误。
这是因为do
记号不同的方式处理故障。 Monad
类型类具有fail
功能。 您正在使用列表monad,它通过返回空列表而失败。 Maybe
monad通过返回Nothing
实现它。 无论哪种方式,里面的模式匹配失败do
记号用此功能,因此区别处理。
所以翻译它的正确方法是:
g xs = Just xs >>=
\xs' -> case xs' of
(x:_) -> return x
[] -> fail "some error"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.