While studying Monads I understood why when pattern matching on list definitions fails, its computation is somewhat "ignored" instead of throwing an error:
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)]
It's because it is just a syntactic sugar for a Monad
application using 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
Similarly, we could try to resemble this logic using the bind operator >>=
:
test'' :: [(Int, Int)]
test'' = [Just 1, Nothing, Just 3] >>= \(Just x) -> [1, 2] >>= \y -> return (x, y)
However, as expected, the monadic function fail
relative to List
will not be called in this situation like it was in the previous ones:
*Main> test''
[(1,1),(1,2)*** Exception: test.hs:11:40-82: Non-exhaustive patterns in lambda
So, my question is: Is it possible to get [(1,1),(1,2),(3,1),(3,2)]
using test''
style, in a neat way? Is do
construct a syntactic sugar for something like this?
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
For instance
{-# LANGUAGE LambdaCase #-}
test'' = [Just 1, Nothing, Just 3] >>= \case
Just x -> [1, 2] >>= \y -> return (x, y)
_ -> fail "..."