问题
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.)
回答1:
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.
回答2:
You are trying to go the wrong way. If something is a transformer, than the plain version of it is the transformer applied to the Identity monad. (They are not always implemented like that directly, but should be equivalent modulo bottom.) But, not all monads are transformers (They need to be universally left or universally right adjoint in order to transform. [citation needed])
hoist and friends are super helpful, too, but I think it best to invert your process.
来源:https://stackoverflow.com/questions/20066858/is-there-a-library-or-typeclass-for-getting-the-transformer-version-of-a-monad