Haskell STM alwaysSucceeds
There is a function in haskell's stm library with the following type signature:
alwaysSucceeds :: STM a -> STM ()
From what I understand of STM in haskell, there are three ways that something can "go wrong" (using that term loosely) while an STM computation is executing:
retry
to make it start over. This effectively makes the thread block and then retry once a TVar in the read set changes. throwSTM
causes this. This one differs from the first two because the transaction doesn't get restarted. Instead, the error is propagated and either crashes the program or is caught in the IO monad. If these are accurate (and if they are not, please tell me), I can't understand what alwaysSucceeds
could possibly do. The always
function, which appears to be built on top of it, seems like it could be written without alwaysSucceeds
as:
--This is probably wrong
always :: STM Bool -> STM ()
always stmBool = stmBool >>= check
The documentation for alwaysSucceeds
says:
alwaysSucceeds adds a new invariant that must be true when passed to alwaysSucceeds, at the end of the current transaction, and at the end of every subsequent transaction. If it fails at any of those points then the transaction violating it is aborted and the exception raised by the invariant is propagated.
But since the argument is of type STM a
(polymorphic in a
), it can't use the value that the transaction returns for any part of the decision making. So, it seems like it would be looking for the different types of failures that I listed earlier. But what's the point of that? The STM monad already handles the failures. How would wrapping it in this function affect it? And why does the variable of type a
get dropped, resulting in STM ()
?
The special effect of alwaysSucceeds
is not how it checks for failure at the spot it's run (running the "invariant" action alone should do the same thing), but how it reruns the invariant check at the end of transactions.
Basically, this function creates a user-specified invariant as in (2) above, that has to hold not just right now, but also at the end of later transactions.
Note that a "transaction" doesn't refer to every single subaction in the STM
monad, but to a combined action that is passed to atomically
.
I guess the a
is dropped just for convenience so you don't have to convert an action to STM ()
(eg with void
) before passing it to alwaysSucceeds
. The return value will be useless anyhow for the later repeated checks.
上一篇: 友好的列表作为更改日志
下一篇: Haskell STM总是会成功