Does a block pattern really need a beat?

While hacking Stack, I found this :

!() <- atomicModifyIORef (eoExeCache eo) $ \m' -> (Map.insert name epath m', ()) 

HLint says, "delete this thing." But I do not think this is a typo. Is there any reason to ever write !() ?

+7
haskell lazy-evaluation
source share
1 answer

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 .

+6
source share

All Articles