If in doubt (and not in a hurry), refer to the specification .
Expression
do !() <- foo bar
desugars up
let ok !() = bar ok _ = fail .. in foo >>= ok
According to the rules for defining a function, this is equivalent
let ok = \x -> case x of !() -> bar _ -> fail ... in foo >>= ok
Now the rules for error patterns are contained in the GHC user guide, as this is a non-standard haskell. there we find that we can rewrite this in
let ok = \x -> x `seq` (case x of () -> bar _ -> fail ...) in foo >>= ok
Now seq determined in terms of its argument β₯ or not. Thus, either x is β₯, but then the second argument is seq , namely case x of ... also β₯ in accordance with the pattern matching semantics. Or x not β₯, and seq is equal to the second argument. In any case, the above code is identical
let ok = \x -> case x of () -> bar _ -> fail ... in foo >>= ok
which by tracking these steps is equivalent
do () <- foo bar
So in conclusion: there is no reason to do this in the do statement.
However, there is a difference between
let () = foo in bar
(where foo will never be appreciated) and
let !() = foo in bar
because let expressions have special semantics for hit patterns .
Joachim breitner
source share