MonadStack- Generalizing lift to monad stacks

Copyright(C) 2015 by Brian Hurt
LicenseBSD 2-Clause
MaintainerBrian Hurt <>
Safe HaskellSafe-Inferred



MonadStack provides a multi-level lift function, called liftFrom. It allows lifting from an arbitrary monad in a monad transformer stack up to any higher monad in that stack. And example use might be:

   newtype MyMonad = MyMonad ... deriving (Monad)

   doFoo :: MonadStack MyMonad m => something -> m whatever
   doFoo arg = liftFrom go
           go :: MyMonad whatever
           go = do ...

This allows calling doFoo either in the MyMonad monad, or in any monad transformer stack on top of the MyMonad.

MonadStack is similar to the Control.Monad.Base module from the transformers-base package, except that there is no functional dependency between the monads. A monad transformer stack can only have one base, but it can have several MonadStack implementations.

MonadStack is very similar to the Control.Monad.Lifter module from the MonadCompose package, with two exceptions. One, MonadStack does not require the OverlappingInstances and UndecidableInstances extensions- both of which are prone to generating hard to diagnose bugs. But this implies two, that MonadStack is much less feature-rich than Lifter is. Specifically, MonadStack only works with "proper" monad transformers (those that implment MonadTrans), while Lifter generalizes the notion of lifting and works with more different types of monads, especially MonadPlus.



class MonadStack m n where Source

A multi-level lifter class.

The existance of an implementation of MonadStack m n implies that is is possible to convert an m a into an n a via zero or more applications of lift.


liftFrom :: m a -> n a Source


MonadStack m m

The base case implementation

You can always convert an m a into an m a by applying 0 lifts. This is like treating an m a as a zero-level monad transformer stack (a monad transformer stack with no monad transformers), and liftFrom is just the id function.

(Monad k, Monad m, MonadTrans n, MonadStack k m) => MonadStack k (n m)

The inductive step implementation

If there exists an implementation of MonadStack k m for monads k and m (that is, we can perform a liftFrom to convert a k a to a m a), and n is a monad transformer, then we can construct an implementation of MonadStack k (n m), by just adding one more lift to the liftFrom.