在研究Monads时,我明白为什么当列表定义上的模式匹配失败时,它的计算在某种程度上被“忽略”而不是抛出错误:
test :: [(Int, Int)]
test = [(x, y) | (Just x) <- [Just 1, Nothing, Just 3], y <- [1, 2]]
*Main> test
[(1,1),(1,2),(3,1),(3,2)]
这是因为它只是使用以下应用程序的语法糖:Monad
do
test'' :: [(Int, Int)]
test'' = do
(Just x) <- [Just 1, Nothing, Just 3]
y <- [1, 2]
return (x, y)
*Main> test'
[(1,1),(1,2),(3,1),(3,2)]
*Main> test == test'
True
同样,我们可以尝试使用绑定运算符 >>=
来模拟这个逻辑:
test'' :: [(Int, Int)]
test'' = [Just 1, Nothing, Just 3] >>= \(Just x) -> [1, 2] >>= \y -> return (x, y)
但是,正如预期的那样,在这种情况下不会像以前那样调用fail
相对于的一元函数:List
*Main> test''
[(1,1),(1,2)*** Exception: test.hs:11:40-82: Non-exhaustive patterns in lambda
所以,我的问题是:是否有可能以一种简洁的方式[(1,1),(1,2),(3,1),(3,2)]
使用风格?test''
是do
为这样的东西构造语法糖吗?
test'' :: [(Int, Int)]
test'' = [Just 1, Nothing, Just 3] >>= \maybeX -> [1, 2] >>= \y -> case maybeX of Just x -> return (x, y)
_ -> fail undefined
*Main> test''
[(1,1),(1,2),(3,1),(3,2)]
*Main> test'' == test
True