Reputation: 491
I was just looking into monad transformers in real world Haskell. The book said that to make something a monad transformer, you need to make it an instance of the MonadTrans type class.
So the book defined a new Transformer, the MaybeT m a
transformer.
They defined the monadTrans type class for this new transformer:
instance MonadTrans MaybeT where
lift m = MaybeT (Just `liftM` m)
Then they made an instance of MonadState for this transformer:
instance (MonadState s m) => MonadState s (MaybeT m) where
get = lift get
put k = lift (put k)
From what I understand the lift function is taking the underlying monad and wrapping it in the right constructor. However, I do not get the implementation of get or put in the MonadState type class, I would like some help in understanding what the lift is actually doing here. I have also heard that in the mtl package because of how the type classes are defined, you can have a stack of monad transformers with WriterT, StateT etc but you can use functions like get,put,tell etc without actually doing any lifting. I was wondering how does this work, I strongly suspect its to do with these type classes but I am not sure?
Upvotes: 4
Views: 574
Reputation: 39370
but you can use functions like get,put,tell etc without actually doing any lifting
This is because those functions are actually defined on e.g. the MonadState
typeclass, not State
type.
class Monad m => MonadState s m | m -> s where
get :: m s
put :: s -> m ()
Then, both State
and StateT
are made an instance of that class, which makes using those possible1
In your example instance, if we know that the inner monad of MaybeT m
is (fulfills) MonadState s
, we can treat the whole outer monad as MonadState s
provided we lift the operations directed to the inner monad so that they fit the outer one, which done with lift
.
In plain english, that would sound something like "If the MaybeT transformer transforms (wraps) over some monad m
that is a stateful (MonadState
) monad for type s
, the resulting type also is a stateful monad for that type".
1This is actually just one instance, because State s a
is actually implemented as StateT s Identity a
. Refer to the sources for the implementation details.
Upvotes: 1