While hacking Stack, I found this:
!() <- atomicModifyIORef (eoExeCache eo) $ \m' ->
(Map.insert name epath m', ())
HLint says: “remove that thing”. But I don't think it's a typo. Is there any reason to ever write !()
?
If in doubt (and not in a hurry) consult the specification.
The expression
do !() <- foo
bar
desugars to
let ok !() = bar
ok _ = fail ..
in foo >>= ok
By the rules for function definition this is equivalent to
let ok = \x -> case x of !() -> bar
_ -> fail ...
in foo >>= ok
Now the rules for bang patterns are in the GHC user guide, as it is non-standard haskell. there we find that we can rewrite this into
let ok = \x -> x `seq` (case x of () -> bar
_ -> fail ...)
in foo >>= ok
Now seq
is defined in terms of its argument being ⊥ or not. So either x
is ⊥, but then the second argument to seq
, namely the case x of ...
is also ⊥ according to the semantics of pattern matching. Or x
is not ⊥, and the seq
equals its second argument. In either case, the above code is identical to
let ok = \x -> case x of () -> bar
_ -> fail ...
in foo >>= ok
which, tracing back these steps, is equivalent to
do () <- foo
bar
So in conclusion: There is no reason to do that in a do
expression.
There is, however, a difference between
let () = foo
in bar
(where foo
will never be evaluated) and
let !() = foo
in bar
because let-expressions have special provisions in the semantics for bang patterns.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With