Haskell STM总是会成功

Haskell的stm库中有一个函数,它具有以下类型的签名:

alwaysSucceeds :: STM a -> STM ()

根据我对haskell中STM的理解,在执行STM计算时,有三种方式可能“出错”(松散地使用该术语):

  • 已经读取的TVar的值由另一个线程改变。
  • 违反了用户指定的不变量。 这似乎通常通过调用retryretry启动来触发。 这有效地使线程阻塞,然后在读取集中的TVar改变后重试。
  • 抛出异常。 调用throwSTM导致这一点。 这与前两个不同,因为事务不会重新启动。 相反,该错误会传播并导致程序崩溃或陷入IO monad中。
  • 如果这些都是准确的(如果它们不是,请告诉我),我不明白什么alwaysSucceeds可能做的。 always功能,似乎是建立在它的上面,看起来好像它可以写成没有alwaysSucceeds的:

    --This is probably wrong
    always :: STM Bool -> STM ()
    always stmBool = stmBool >>= check
    

    alwaysSucceeds的文档说:

    alwaysSucceeds添加了一个新的不变量,在传递给alwaysSucceeds时,在当前事务结束时以及在每个后续事务结束时都必须为true。 如果它在任何这些点上失败,那么违反它的事务将被中止,并且由不变量引发的异常将被传播。

    但由于参数的类型为STM a (多态a ),它不能使用该交易的决策的任何部分返回值。 所以,它似乎在寻找我之前列出的不同类型的故障。 但是,这有什么意义呢? STM monad已经处理了这些故障。 如何将它包裹在这个函数中影响它呢? 为什么类型a的变量会丢失,导致STM ()


    alwaysSucceeds的特殊效果并不是它在它运行的地方检查失败(运行“不变”操作本身应该做同样的事情),而是它如何在事务结束时重新执行不变检查。

    基本上,这个函数创建了一个用户指定的不变量,如上面(2)所示,它不得不保持在现在,而且还在后面的事务结束时。

    请注意,“交易”不是指STM monad中的每一个子动作,而是指以atomically方式传递的组合动作。

    为了方便起见,我认为a被放弃了,所以在将它传递给alwaysSucceeds之前,你不必将一个动作转换成STM () (例如用void )。 无论如何,返回值对于稍后的重复检查都是无用的。

    链接地址: http://www.djcxy.com/p/81457.html

    上一篇: Haskell STM alwaysSucceeds

    下一篇: Does reading a TChan result in blocking or polling?