In my current project I've run into the need to turn various monads into their transformer counterparts e.g.
stateT :: Monad m => State s a -> StateT s m a
stateT stf = StateT $ return . runState stf
It's trivial to write these utility functions for the monads I need, but I was wondering if there already exists a library that contains this functionality for the standard monads and maybe a typeclass that abstracts this sort of transformation. Something like
class (Monad f, MonadTrans t) => LiftTrans f t | f -> t where
liftT :: Monad m => f a -> t m a
("lift" is probably the wrong term to use here, but I wasn't sure what else to call it.)
Check out function hoist
from the mmorph package.
Its signature is
hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b
Meaning that it can change the base monad underlying a transformer.
Now, in the trasformers
package, many "basic" monads are implemented as transformers applied to the Identity
monad, like this:
type State s = StateT s Identity
Therefore, we can define the following function (taken form the Generalizing base monads section of the mmorph
documentation):
import Data.Functor.Identity
generalize :: (Monad m) => Identity a -> m a
generalize m = return (runIdentity m)
and combine it with hoist:
hoist generalize :: (Monad m, MFunctor t) => t Identity b -> t m b
This method won't work for simple monads which are not defined as transformers applied to Identity
, like the Maybe
and Either
monads. You are stuck with hoistMaybe and hoistEither for these.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With