3

To put into context, I was converting a list comprehension (from there) doing "pattern filtering" to its monadic counterpart (do and bind), then I meet an exception.

I start with these definitions (bf holds for breadthFirst),

context, data and helper

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])

function to test

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)

And I do these evaluations,

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

But I learned from there

The do syntax provides a simple shorthand for chains of monadic operations. The essential translation of do is captured in the following two rules:

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

Why does bfBind fail contrary to bfDo despite they are equivalent ?
Personally, I was expected they all failed, I don't know why list comprehension or Do notation succeed ? (Then if you can answer also this sub question)

Thanks.

4

1 回答 1

6

do发生这种情况是因为符号中失败的模式匹配调用fail了 Monad 类中的函数。

特别是,这就是您的表达式实际上被脱糖的方式:

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

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

(查看Haskell 报告中关于do 表达式的部分。)

Monad实例[]定义fail如下:

fail _ = []
于 2013-05-10T23:51:00.567 回答