Reputation: 1195
I have the following code snippet, where assert is used to check an invariant regarding some internal state. However, assert
is never evaluated and thus never fails even when it should, probably because return
is not evaluated when returning type ()
. This holds even if I change to assert False
. Any way to fix this?
FooM :: m () // m is a monad
FooM = do
state <- get
// some state mutation
state' <- get
return $ assert (state /= state') ()
return $ assert False () // <-- this also never fails
Upvotes: 0
Views: 82
Reputation: 29193
return $ assert (state /= state') ()
is evaluated, because the monadic >>=
needs to evaluate it to figure out "what to execute" (it just so happens that that is "nothing"). But though the action is evaluated, the value assert (state /= state') ()
contained in that action is not, because it isn't used. The solution is to guard the action return ()
with assert
, not the (ignored) value ()
.
assert (state /= state') $ return ()
Alternatively,
return $! assert (state /= state') ()
-- = let arg = assert (state /= state') () in arg `seq` return arg
-- for evaluation to "get to" the return, the assertion must succeed
Upvotes: 3