haskell的stm库中有一个带有以下类型签名的函数:
alwaysSucceeds :: STM a -> STM ()
Run Code Online (Sandbox Code Playgroud)
根据我对haskell中STM的理解,有三种方法可以在执行STM计算时"出错"(使用该术语):
retry重启来触发的.这有效地使线程阻塞,然后一旦读取集中的TVar改变就重试.throwSTM会导致这种情况.这个与前两个不同,因为事务没有重新启动.相反,错误会传播并导致程序崩溃或被IO monad捕获.如果这些是准确的(如果不是,请告诉我),我无法理解alwaysSucceeds可能做什么.该always函数似乎构建在它之上,看起来它可以写成没有alwaysSucceeds:
--This is probably wrong
always :: STM Bool -> STM ()
always stmBool = stmBool >>= check
Run Code Online (Sandbox Code Playgroud)
文档alwaysSucceeds说:
alwaysSucceeds添加了一个新的不变量,当传递给alwaysSucceeds时,在当前事务结束时以及每个后续事务结束时都必须为true.如果它在任何这些点失败,那么违反它的事务将被中止,并且传播由不变量引发的异常.
但由于参数是类型STM a(多态a),因此它不能使用事务为决策制定的任何部分返回的值.所以,似乎它会寻找我之前列出的不同类型的故障.但那有什么意义呢?STM monad已经处理了故障.如何将它包装在此函数中会影响它?为什么类型的变量会a被丢弃,导致STM ()?
特殊效果alwaysSucceeds不是它如何检查它运行的位置的失败(单独运行"不变"操作应该做同样的事情),但它如何在事务结束时重新运行不变检查.
基本上,这个函数创建一个用户指定的不变量,如上面的(2)所示,它不仅要保持现在,还要保留在以后的事务结束时.
请注意,"事务"不是指STMmonad 中的每个子操作,而是指传递给的组合操作atomically.
我想这a是为了方便而丢弃的,所以你不必在传递之前将动作转换为STM ()(例如with void)alwaysSucceeds.对于后来的重复检查,返回值无论如何都是无用的.