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
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
.