After the | in list comprehension, pattern matching can be used to filter expected values.

Useful syntax

It’s actually extremely useful syntax and adds a lot of expression power to list comprehension. The well-known catMaybes can be implemented in this way as:

catMaybes :: [Maybe a] -> [a]
catMaybes ms = [x | Just x <- ms]

If the pattern matching failed, it just move to next element in the list, avoiding explicit handing constructors we are not interested in.

fail in Monad

Why failure of pattern matching doesn’t cause an error? What happens when pattern matching fails in list comprehension?

In session 3.11 of Haskell 2010 Language Report, in list comprehension if a match fails then that element of the list is simply skipped over. There’s a desugar rule:

[ e | p <- l, Q ] = let ok p = [ e | Q ]
                        ok _ = []
                     in concatMap ok  l

But, we must wonder why define such a rule? The underlying fact is that list is a monad in Haskell. Function catMaybes can be implemented with do notation:

catMaybes :: [Maybe a] -> [a]
catMaybes ms = do
    Just x <- ms
    return x

If pattern matching fails in a binding within do notation, the fail method of a monad instance will be called. In Haskell 2010 Language Report session 3.14, the desugar rule is:

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

And, when instantiate [] as a Monad, the fail is:

fail _ = []

Now, it’s trivial to understand why mismatching isn’t an error. For other monad when pattern matching fails the fail method will be called. IO, for example, if pattern mismatch, failIO will be called and an exception will be throw out.