为什么有充分的理由使check
库中的Contol.Concurent.STM
函数具有Bool -> STM a
类型,并在成功时返回undefined
而不是具有Bool -> STM ()
类型?类型检查器的实现方式将通过polity编译一个以check foo
结尾的do块,仅在运行时使用*** Exception: Prelude.undefined
失败。
最佳答案
看起来这是GHC PrimOp的占位符定义,例如“definition” seq _ y = y
被编译器替换为实际的原始实现代码。 PrimOp implementation of check
接受一个表达式并将其添加到STM invariants paper中描述的不变量的全局列表中。
这是从该论文修改而来的新示例,以适应新的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
实际上,这对于在共享状态下声明不变式很有用,因为如果声明失败,则可能表示暂时的不一致。然后,您可能希望重试该不变量最终最终变为true的期望,但是由于此示例永久性地破坏了该不变量,因此它只会永久调用
retry
并似乎挂起。请查看本文以获取更好的示例,但请记住,自发布以来,该类型已发生变化。关于Haskell STM检查函数返回未定义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8364903/