Teach strictness analysis about `catch`-like operations
catch# :: (State# RealWorld -> (# State# RealWorld, a #) ) -- ^ thing to catch exceptions from -> (b -> State# RealWorld -> (# State# RealWorld, a #) ) -- ^ exception handler -> State# RealWorld -> (# State# RealWorld, a #)
Semantically, this operation will always evaluate its first argument. Ideally we would indicate this in the primop's strictness signature in
primops.txt.pp. Sadly, we can't do this at the moment due to a subtle wrinkle (discovered in #10712 (closed)):
let r = \st -> raiseIO# blah st in catch (\st -> ...(r st)..) handler st
If we give the first argument of catch a strict signature, we'll get
r; that is,
r is definitely called with one
argument, which indeed it is. The trouble comes when we feed
r's RHS as the demand of the body as this will lead us to conclude that
let will diverge; clearly this isn't right.
As Simon noted in ticket:10712#comment:103206,
There's something very special about catch: it turns divergence into non-divergence.
In order to apply a proper strictness signature to
catch-like operations we would need to teach the strictness analyzer about this property.