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:

  • The value of an TVar that has been read is changed by another thread.
  • An user-specified invariant is violated. This seems to usually be triggered by calling retry to make it start over. This effectively makes the thread block and then retry once a TVar in the read set changes.
  • An exception is thrown. Calling 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.

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

    上一篇: 友好的列表作为更改日志

    下一篇: Haskell STM总是会成功