{-| This module is the indexed equivalent to @Control.Monad.Trans.Class@ from the @transformers@ package. -} {-# LANGUAGE TypeOperators #-} module Control.IMonad.Trans ( -- * Monad Transformers -- $transform IMonadTrans(..), liftU ) where import Control.Category.Index import Control.IMonad.Core import Control.IMonad.Restrict {- $transform Indexed monad transformers transform computations in a base /indexed/ monad into a higher /indexed/ monad layered on top of the base monad. Note that this does not lift ordinary monads. To do that you must first convert the ordinary monad to a restricted monad using the 'u' function from "Control.IMonad.Restrict" and then use 'liftI' like so: > -- Using indexed do notation provided by Control.IMonad.Do > do x <- indexedActionInHigherMonad > liftI $ u $ ordinaryActionInBaseMonad x -} {-| An indexed monad transformer. All instances must satisfy the monad transformer laws: > liftI . returnI = returnI > > liftI . (f >?> g) = (liftI . f) >?> (liftI . g) -} class IMonadTrans t where liftI :: (IMonad m) => m a :-> t m a {-| Lifts ordinary monads for restricted monad transformers > liftU = liftI . u -} liftU :: (Monad m, IMonadTrans t) => m a -> t (U m) (a := i) i liftU = liftI . u