Haskell的stm库中有一个函数,其类型签名如下:
alwaysSucceeds :: STM a -> STM ()
据我理解,Haskell中的STM在执行计算时可能会发生三种“出错”(宽泛地使用这个术语)的情况:
- 已读取的TVar的值被另一个线程更改。
- 违反了用户指定的不变量。这似乎通常是通过调用
retry
使其重新开始启动的。这实际上使线程阻塞,然后在读取集合中的TVar更改后重试一次。 - 抛出异常。通过调用
throwSTM
引发异常。这种情况与前两种不同,因为事务不会重新启动。相反,错误会传播并且要么使程序崩溃,要么在IO单子中被捕获。
如果这些准确(如果不是,请告诉我),我就不能理解alwaysSucceeds
到底能做什么。看起来构建在其上的always
函数可以在没有alwaysSucceeds
的情况下编写:
--This is probably wrong
always :: STM Bool -> STM ()
always stmBool = stmBool >>= check
alwaysSucceeds
的文档说明如下:
但是,由于参数的类型为
alwaysSucceeds
添加一个新的不变式,该不变式必须在传递给它时为真,在当前事务结束时以及每个随后的事务结束时也必须为真。如果它在任何这些点上失败,则违反它的事务将被中止,并传播不变式引发的异常。
STM a
(多态的a
),因此它不能使用事务返回的值来制定任何决策部分。所以,似乎它会寻找我前面列出的不同类型的故障。但这有什么意义呢?STM monad已经处理了这些故障。将其包装在此函数中会产生什么影响?以及为什么类型为a
的变量被删除,导致STM ()
?