Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a library or typeclass for getting the transformer version of a monad?

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.)

like image 457
shang Avatar asked Nov 19 '13 08:11

shang


1 Answers

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.

like image 131
danidiaz Avatar answered Oct 19 '22 03:10

danidiaz