I have looked at this to try to understand how several transformer monads interact, and especially getting a better understanding of lift
and stacking with monads.
For the RWST monad found here (I think this is the best documentation of it), is it the case that it is a stacked monad where the Reader, Writer, State each are a monadic layer (and in that order of stacking). Or how is it supposed to be understood?
When I look at the definition runRWST :: r -> s -> m (a, s, w)
I understand it as taking reader-environment a state-environment and wrapping any monad m
around the return value of RWS
. This also means that there only exists two layers of monads in this monad. That is, the outer monad m
, and a tuple containing several monads.
This in turn also means that you can only use the lift
once. Lifting a value from either the reader or the state monad into the outer monad.
In that sense get
and ask
are just two functions applying one of either two of the inner monads. For this last point I am still not sure I understand why you would need both a reader a state-monad even having read this stackoverflow post. The reader is only meaningfull for read-only I guess, but if one didn't want that, could one use a transformer monad around two seperat state-monads?
The comments have given me reason to ponder and make the following more explicit.... Of the following type definition what what would be the inner monad, and the outer monad? Is the RWST
itself a Monad wrapped around (and therefor an outer monad) Either String
(the inner monad) ?
type MyRWST a = RWST
(String -> Either String MyType)
[Int]
(MyEnv, [String], [String])
(Either String)
a
The inner monad of a monad transformer is always a type parameter. The type you've provided isn't a transformer.
type MyRWST a = RWST
(String -> Either String MyType)
[Int]
(MyEnv, [String], [String])
(Either String)
a
This is a Monad
. Compare this to a transformer like MaybeT
.
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
MaybeT
takes two type parameters, and the first itself takes a parameter, so its kind is (* -> *) -> * -> *
. With more explicit parentheses, that's (* -> *) -> (* -> *)
. And now we can see why it's called a transformer. It takes one monad (of kind * -> *
) and transforms it into a new monad (also of kind * -> *
).
RWST
is defined as
newtype RWST r w s m a = RWST { unRWST :: r -> s -> w -> m (a, s, w) }
Now this takes a lot of type arguments, but if we fix r
, w
, and s
, we get a transformer. That is, RWST
is not, itself, a monad transformer, but for any r
, w
, and s
, RWST r w s
is a transformer. The full kind of RWST
is
RWST :: * -> * -> * -> (* -> *) -> * -> *
And while you can think of RWST
as having three layers (reader, writer, and state), it really only does have one. The "next layer down" of RWST r w s m
is really m
. So to directly answer your question about lift
, the type signature of lift
is
lift :: (MonadTrans t, Monad m) => m a -> t m a
and when t ~ RWST r w s
, we get
lift :: Monad m => m a -> RWST r w s m a
So a single lift
takes us over the whole RWST r w s
mess.