check
有充分的理由吗? Contol.Concurent.STM
中的函数库的类型为 Bool -> STM a
并返回 undefined
成功而不是类型Bool -> STM ()
?它的实现方式类型检查器将编译一个以 check foo
结尾的 do block 只是在运行时失败 *** Exception: Prelude.undefined
.
最佳答案
它看起来像是 GHC PrimOp 的占位符定义,如“定义”seq _ y = y
它被编译器替换为实际的原始实现代码。 PrimOp implementation of check
如STM invariants paper 中所述,获取一个表达式并将其添加到不变量的全局列表中。 .
这是从那篇论文修改的一个 super 设计的例子,以适应 check
的新类型。 :
import Control.Concurrent.STM
data LimitedTVar = LTVar { tvar :: TVar Int
, limit :: Int
}
newLimitedTVar :: Int -> STM LimitedTVar
newLimitedTVar lim = do
tv <- newTVar 0
return $ LTVar tv lim
incrLimitedTVar :: LimitedTVar -> STM ()
incrLimitedTVar (LTVar tv lim) = do
val <- readTVar $ tv
let val' = val + 1
check (val' <= lim)
writeTVar tv val'
test :: STM ()
test = do
ltv <- newLimitedTVar 2
incrLimitedTVar ltv -- should work
incrLimitedTVar ltv -- should work still
incrLimitedTVar ltv -- should fail; we broke the invariant
实际上,这对于在共享状态上断言不变量很有用,其中断言失败可能是暂时不一致的标志。然后,您可能希望重试该不变量最终再次变为真,但由于此示例最终会永久破坏该不变量,因此它只调用
retry
永远,似乎挂起。查看该论文以获得更好的示例,但请记住,该类型自发布以来已发生变化。
关于Haskell STM检查函数返回未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8364903/