Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching in do notation vs let

I recently encountered an error while using threepenny-gui and it was solved by changing the code from pattern match in the do notation with <- to pattern matching with the let notation.

Is there any reasons why I should expect a change in behavior when changing between these two forms of pattern matching?

Specifically the following code:

In the IO monad:

Just events <- Map.lookup elid <$> readMVar sElementEvents

was changed to:

mevents <- Map.lookup elid <$> readMVar sElementEvents
let Just events = mevents

Here is a link to the commit the fixed the problem for me: https://github.com/Davorak/threepenny-gui/commit/fbf6cbe25875fafdc64f7a111ddebf485b45143b

Additional platform details: os: 10.8.5 ghc: 7.6.3

edit: added the fact that this is happening the IO monad

like image 539
Davorak Avatar asked Nov 17 '13 02:11

Davorak


1 Answers

Actually, yes, they produce different kinds of errors. Missing a pattern match in a let binding raises a pattern match error whenever that match is evaluated while missing a pattern match from (<-) just calls the Monad instance's fail function

As a simple example, consider the Maybe monad where

instance Monad Maybe where
  ...
  fail _ = Nothing

test1 :: Maybe (Maybe ())
test1 = do
  Just a <- return Nothing
  return a

test2 :: Maybe (Maybe ())
test2 = do
  ma <- return Nothing
  let Just a = ma
  return a

If we call both of them, we get wildly different behavior

> test1
Nothing

> test2
Just *** Exception: PM.hs:23:7-17: 
Irrefutable pattern failed for pattern Data.Maybe.Just a

Generally irrefutable matching is a bad idea unless you're really certain it's impossible to get the missing patterns, but if you must do it in a Monad then sometimes irrefutable matching on a bind is better than in a let.

like image 181
J. Abrahamson Avatar answered Sep 27 '22 20:09

J. Abrahamson