我有来自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)
Run Code Online (Sandbox Code Playgroud)
上面的代码按预期工作.以下是我的主要功能和打印结果:
main = print $ combinations 2 "abcd"
-- Prints: ["ab","ac","ad","bc","bd","cd"]
Run Code Online (Sandbox Code Playgroud)
作为一个学习练习,我试图"desugar"这样的记号:
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = return []
combinations n xs = tails xs >>= \(y:xs') ->
do
ys <- combinations (n-1) xs'
return (y:ys)
Run Code Online (Sandbox Code Playgroud)
这会编译,但在运行时会出现以下错误:
PatternMatchFail: /home/.../test.hs:(46,34)-(49,37): Non-exhaustive patterns in lambda
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?如何用>>=和替换do-notation >>?
Ben*_*esh 15
......与lambdas的片段与do块"大致相同".它不是一个精确的转换,因为符号添加了模式匹配失败的特殊处理.
考虑这个例子:
f xs = do
(x:_) <- Just xs
return x
g xs = Just xs >>=
\(x:_) -> return x
Run Code Online (Sandbox Code Playgroud)
对于任何非空列表,这些功能都是相同的.但f []返回Nothing,并g []返回一个错误,就像你得到的错误.
这是因为do符号处理失败的方式不同.该Monad类型类具有fail的功能.您正在使用列表monad,它通过返回空列表而失败.该Maybe单子通过返回实现它Nothing.无论哪种方式,do符号内的模式匹配失败都是用这个函数处理的,因此存在差异.
所以翻译它的正确方法是:
g xs = Just xs >>=
\xs' -> case xs' of
(x:_) -> return x
[] -> fail "some error"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
560 次 |
| 最近记录: |