非穷举模式异常,用于绑定但不用于执行

时间:2013-05-10 23:46:21

标签: haskell pattern-matching list-comprehension monads

为了进入上下文,我正在将列表理解(从there)转换为“模式过滤”到其monadic对应物(do和bind),然后我遇到异常。

我从这些定义开始(bf为breadthFirst持有),

上下文,数据和帮助

data Tree a = Leaf | Node a (Tree a) (Tree a) deriving Show
let test = Node 1 (Node 2 (Node 4 Leaf Leaf) Leaf) (Node 3 Leaf (Node 5 Leaf Leaf))
let nextChild = concatMap (\x -> case x of; Leaf -> []; Node n l r -> [l,r])

测试功能

let bfLc xs   | null xs = [] | otherwise = [ n | Node n _ _ <- xs] ++ (bfLc $ nextChild xs)   
let bfDo xs   | null xs = [] | otherwise = (do {Node n _ _ <- xs; return n})  ++ (bfDo $ nextChild xs)
let bfBind xs | null xs = [] | otherwise = (xs >>= \(Node n _ _) -> [n]) ++ (bfBind $ nextChild xs)

我做了这些评估,

bfLc [test]
[1,2,3,4,5]

bfDo [test]
[1,2,3,4,5]

bfBind [test]
[1,2,3,4*** Exception: <interactive>:103:53-72: Non-exhaustive patterns in lambda

但我从there

学习
  

do语法为monadic操作链提供了一个简单的简写。 do的基本翻译遵循以下两条规则:

  do e1 ; e2      =  e1 >> e2  
  do p <- e1; e2  =  e1 >>= \p -> e2  

为什么bfBind失败与bfDo相反,尽管它们是等价的? 就个人而言,我原本以为他们都失败了,我不知道为什么列表理解或者记谱法成功了? (那么如果你也可以回答这个子问题)

感谢。

1 个答案:

答案 0 :(得分:6)

这是因为do表示法中的失败模式匹配从Monad类调用fail函数。

特别是,这就是你的表达实际上被贬低的方式:

do {p <- e; stmts}  = let ok p = do {stmts}
                          ok _ = fail "..."
  in e >>= ok

此处p是任何模式,例如您示例中的Node n _ _

(请参阅Haskell报告中do expressions部分。)

Monad的{​​{1}}实例定义[],如下所示:

fail