[Haskell-cafe] Why Haskell?

Viktor Dukhovni ietf-dane at dukhovni.org
Mon Mar 29 11:50:59 UTC 2021

On Mon, Mar 29, 2021 at 07:11:49PM +0800, YueCompl via Haskell-Cafe wrote:

> But AFAICT, STM composes poorly with other monads in today's mtl
> fashion, and by itself I don't think effects are tracked sufficiently
> well. 
> I'm not aware of an idiomatic way to properly have STM in a monad
> stack, or is it there?

STM is not a monad transformer, but it is a fine base monad, just like
Identity, IO or ST.  Here's a contrived example of (StateT Int STM Int):

    import Control.Concurrent.STM
    import Control.Monad (when)
    import Control.Monad.Trans.State.Strict
    import Control.Monad.Trans.Class (lift)

    main :: IO ()
    main = do
       tv <- newTVarIO 0
       y <- atomically $ flip evalStateT 0 $ do
           x <- get
           lift $ do
               modifyTVar tv (\a -> a + x + 1)
               y <- readTVar tv
               when (y > 10) retry
               return y
       print y

So any or all of RWST work with STM, but you typically want to keep your
STM transactions small and simple, so this is not a place where one
would generally run wild with fancy stacks that do non-trivial
additional computation.

Indeed Monad Transformers are not Monads, they're always stacked on top
of some base monad.  The turtles don't go all the way down.

A practical example of STM-like Monad's can be found in Hasql, where
database operations run in a Monad that ensures that they have no
side-effects that would prevent the transaction from being retried on
deadlock detection.  This is also a base Monad, where if you like
you can stack more (pure) transformers.

Which reminds me that ExceptT can be useful in such Monads, which
avoid throwing impure exceptions.  And is used in Hasql, where
the operations tend to be more expensive than in STM, and any
overhead from layering ExceptT or similar is quite small.


More information about the Haskell-Cafe mailing list