【发布时间】:2014-09-06 22:28:42
【问题描述】:
haskell 的 stm 库中有一个函数,其类型签名如下:
alwaysSucceeds :: STM a -> STM ()
根据我对 Haskell 中 STM 的理解,在执行 STM 计算时,有三种方式可能会“出错”(松散地使用该术语):
- 已读取的 TVar 的值被另一个线程更改。
- 违反了用户指定的不变量。这似乎通常通过调用
retry来触发以使其重新开始。这有效地使线程阻塞,然后在读取集中的 TVar 更改后重试。 - 引发异常。调用
throwSTM会导致这种情况。这与前两个不同,因为事务不会重新启动。相反,错误会被传播,或者导致程序崩溃,或者被 IO monad 捕获。
如果这些是准确的(如果不是,请告诉我),我无法理解 alwaysSucceeds 可能会做什么。 always 函数似乎是建立在它之上的,似乎可以在没有 alwaysSucceeds 的情况下编写为:
--This is probably wrong
always :: STM Bool -> STM ()
always stmBool = stmBool >>= check
alwaysSucceeds 的文档说:
alwaysSucceeds 添加一个新的不变量,当传递给 alwaysSucceeds,在当前事务结束时,在结束时 以后的每一笔交易。如果它在任何这些点失败 然后违反它的事务被中止并引发异常 由不变量传播。
但由于参数是STM a 类型(a 中的多态),它不能使用事务返回的值用于决策的任何部分。因此,它似乎会寻找我之前列出的不同类型的故障。但那有什么意义呢? STM monad 已经处理了失败。将它包装在这个函数中会如何影响它?还有为什么a类型的变量会被丢弃,导致STM ()?
【问题讨论】:
-
因为你的评论提醒了我:有一个current GHC proposal to deprecate this feature。