Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - How does a pattern match fail in a list comprehension?

I'm learning Haskell with Miran Lipovaca's "Learn You a Haskell for Great Good!". In page 82 it says

If a pattern match fails, the list comprehension will just move on to the next element, and the element that failed won’t be included in the resulting list.

Example:

ghci> let xs = [(1,3),(4,3),(2,4),(5,3),(5,6),(3,1)]
ghci> [a+b | (a, b) <- xs]
[4,7,6,8,11,4]

My question is how does a pattern match fail? What does he mean by that? I really don't get it. It could be because of my weak english. I please you for an example because I think the book doesn't give any example for failing pattern match.

I thought about something like if the list contains a type that couldn't be processed by the list comprehension then it moves to the next element but if I change the list in this way:

let xs = [(1,3),(4,3),(2,4),(5,3),True,(5,6)]

Then it doesn't even compile because it "couldn't match expected type"...

like image 560
CoreNoob Avatar asked Mar 11 '18 22:03

CoreNoob


2 Answers

Here are a few cases of failing pattern matching in list comprehensions, demoed in GHCi:

Prelude> [ () | True <- [True, False,True] ]
[(),()]
Prelude> [ x | (x, True) <- [(1,True), (2,False), (3,True)] ]
[1,3]
Prelude> [ x+1 | Left x <- [Left 1, Right "Hello", Right "world", Left 2] ]
[2,3]

Note that some patterns can never fail, e.g. x, (x,y), or (x,(a,b),z). This is because they match types having only a constructor, which has to match being the only one.

In general, pattern matching involves multiple branches, e.g.

case someValue of
   Left x  -> ...
   Right y -> ...

foo Nothing = ...
foo (Just x) = ...

In these cases, if we forget to handle a constructor, we get a runtime error when that case occurs. (Turning on warnings helps in avoiding this!).

In list comprehensions generators p <- ..., instead, we can only specify one pattern. However, a special rule applies: failure of pattern matching is not an error, but is simply ignored.

like image 177
chi Avatar answered Sep 27 '22 20:09

chi


That's not an example of pattern-match failure (the tuple pattern matches always). This would be an example:

Prelude> xs = [Just (1,3), Just (4,3), Nothing, Just (5,3), Nothing]
Prelude> [a+b | Just (a, b) <- xs]
[4,7,8]

Here, the pattern Just (a, b) matches only the elements Just (1,3), Just (4,3) and Just (5,3), but not the Nothings, so these positions just don't turn up in the final list.

like image 45
leftaroundabout Avatar answered Sep 27 '22 21:09

leftaroundabout