我有以下代码片段,其中assert用于检查有关某些内部状态的不变量。然而,assert
永远不会被求值,因此即使在应该求值的时候也不会失败,这可能是因为当返回类型()
时,return
不会被求值。即使我更改为assert False
,这也成立。有办法解决这个问题吗?
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
return $ assert (state /= state') ()
被求值,因为一元的>>=
需要求值以确定"执行什么";(碰巧那是"没什么")。但是,尽管操作被求值,但是该操作中包含的值assert (state /= state') ()
没有被求值,因为它没有被使用。解决方案是用assert
来保护动作return ()
,而不是(被忽略的)值()
。
assert (state /= state') $ return ()
或者
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