断言未在 return () 中求值

assert is not evaluated in return ()

我有以下代码片段,其中 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') () 评估,因为 monadic >>= 需要评估它以确定“执行什么”(恰好是没什么”)。但是,虽然 action 被评估了,但该操作中包含的 value assert (state /= state') () 没有被评估,因为它没有被使用。解决方案是用 assert 保护 action 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