deriving-trans-0.5.1.0: Derive instances for monad transformer stacks
Safe HaskellSafe-Inferred
LanguageHaskell2010

Control.Monad.Trans.Elevator

Synopsis

Elevator

Elevator can be used to lift instances through monad transformers as long as they implement a MonadTrans / MonadTransControl / MonadTransControlIdentity instance.

MonadTransControl is only necessary when there is atleast one method with a monadic argument. MonadTransControlIdentity is even stronger and only required for a few specific instances.

newtype Elevator t m a Source #

A newtype wrapper for monad transformers.

Access instances of the inner monad m.

Type level arguments:

t :: (Type -> Type) -> Type -> Type
monad transformer
m :: Type -> Type
monad
a :: Type
value

Constructors

Ascend 

Fields

Instances

Instances details
(Monad (t m), MonadTransControl t, MonadRWS r w s m) => MonadRWS r w s (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

(Monad (t m), MonadTransControl t, MonadBaseControl b m) => MonadBaseControl b (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Associated Types

type StM (Elevator t m) a #

Methods

liftBaseWith :: (RunInBase (Elevator t m) b -> b a) -> Elevator t m a #

restoreM :: StM (Elevator t m) a -> Elevator t m a #

(Monad (t m), MonadTransControlIdentity t, MonadBaseControlIdentity b m) => MonadBaseControlIdentity b (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

liftBaseWithIdentity :: ((forall x. Elevator t m x -> b x) -> b a) -> Elevator t m a #

(Monad (t m), MonadTransControl t, MonadError e m) => MonadError e (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

throwError :: e -> Elevator t m a #

catchError :: Elevator t m a -> (e -> Elevator t m a) -> Elevator t m a #

(Monad (t m), MonadTransControl t, MonadReader r m) => MonadReader r (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

ask :: Elevator t m r #

local :: (r -> r) -> Elevator t m a -> Elevator t m a #

reader :: (r -> a) -> Elevator t m a #

(Monad (t m), MonadTrans t, MonadState s m) => MonadState s (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

get :: Elevator t m s #

put :: s -> Elevator t m () #

state :: (s -> (a, s)) -> Elevator t m a #

(Monad (t m), MonadTransControl t, MonadWriter w m) => MonadWriter w (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

writer :: (a, w) -> Elevator t m a #

tell :: w -> Elevator t m () #

listen :: Elevator t m a -> Elevator t m (a, w) #

pass :: Elevator t m (a, w -> w) -> Elevator t m a #

(Monad (t m), MonadTrans t, MonadBase b m) => MonadBase b (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

liftBase :: b α -> Elevator t m α #

MonadTransControl t => MonadTransControl (Elevator t) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Associated Types

type StT (Elevator t) a #

Methods

liftWith :: Monad m => (Run (Elevator t) -> m a) -> Elevator t m a #

restoreT :: Monad m => m (StT (Elevator t) a) -> Elevator t m a #

MonadTransControlIdentity t => MonadTransControlIdentity (Elevator t) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

liftWithIdentity :: Monad m => ((forall x. Elevator t m x -> m x) -> m a) -> Elevator t m a #

MonadTrans t => MonadTrans (Elevator t) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

lift :: Monad m => m a -> Elevator t m a #

(Monad (t m), MonadTrans t, MonadFail m) => MonadFail (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

fail :: String -> Elevator t m a #

(Monad (t m), MonadTransControlIdentity t, MonadFix m) => MonadFix (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

mfix :: (a -> Elevator t m a) -> Elevator t m a #

(Monad (t m), MonadTrans t, MonadIO m) => MonadIO (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

liftIO :: IO a -> Elevator t m a #

(Monad (t m), MonadTransControlIdentity t, MonadZip m) => MonadZip (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

mzip :: Elevator t m a -> Elevator t m b -> Elevator t m (a, b) #

mzipWith :: (a -> b -> c) -> Elevator t m a -> Elevator t m b -> Elevator t m c #

munzip :: Elevator t m (a, b) -> (Elevator t m a, Elevator t m b) #

(Monad (t m), MonadTransControl t, Monad m, Alternative m) => Alternative (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

empty :: Elevator t m a #

(<|>) :: Elevator t m a -> Elevator t m a -> Elevator t m a #

some :: Elevator t m a -> Elevator t m [a] #

many :: Elevator t m a -> Elevator t m [a] #

Applicative (t m) => Applicative (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

pure :: a -> Elevator t m a #

(<*>) :: Elevator t m (a -> b) -> Elevator t m a -> Elevator t m b #

liftA2 :: (a -> b -> c) -> Elevator t m a -> Elevator t m b -> Elevator t m c #

(*>) :: Elevator t m a -> Elevator t m b -> Elevator t m b #

(<*) :: Elevator t m a -> Elevator t m b -> Elevator t m a #

Functor (t m) => Functor (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

fmap :: (a -> b) -> Elevator t m a -> Elevator t m b #

(<$) :: a -> Elevator t m b -> Elevator t m a #

Monad (t m) => Monad (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

(>>=) :: Elevator t m a -> (a -> Elevator t m b) -> Elevator t m b #

(>>) :: Elevator t m a -> Elevator t m b -> Elevator t m b #

return :: a -> Elevator t m a #

(Monad (t m), MonadTransControl t, MonadPlus m) => MonadPlus (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

mzero :: Elevator t m a #

mplus :: Elevator t m a -> Elevator t m a -> Elevator t m a #

(Monad (t m), MonadTransControl t, MonadCatch m) => MonadCatch (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

catch :: Exception e => Elevator t m a -> (e -> Elevator t m a) -> Elevator t m a #

(Monad (t m), MonadTrans t, MonadThrow m) => MonadThrow (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

throwM :: Exception e => e -> Elevator t m a #

(Monad (t m), MonadTransControl t, MonadCont m) => MonadCont (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

callCC :: ((a -> Elevator t m b) -> Elevator t m a) -> Elevator t m a #

(Monad (t m), MonadTransControlIdentity t, MonadUnliftIO m) => MonadUnliftIO (Elevator t m) Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

Methods

withRunInIO :: ((forall a. Elevator t m a -> IO a) -> IO b) -> Elevator t m b #

type StT (Elevator t) a Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

type StT (Elevator t) a = StT t a
type StM (Elevator t m) a Source # 
Instance details

Defined in Control.Monad.Trans.Elevator

type StM (Elevator t m) a = StM m (StT t a)

Examples

Example 1: Recover submerged instances

Let's assume you want to define a monad transformer stack.

newtype StackT m a = StackT { unStackT :: ReaderT Char (ReaderT Bool m) a }
  deriving newtype (Functor, Applicative, Monad)

Now you want to expose the inner (MonadReader Bool) instance with (StackT m).

Normally it's shadowed by the (MonadReader Char) instance, but we can use Elevator to access the inner transformer.

  deriving (MonadReader Bool) via Elevator (ReaderT Char) (ReaderT Bool m)

Example 2: Custom transformer without boilerplate

Let's assume you have defined a monad transformer.

newtype CustomT m a = CustomT { unCustomT :: IdentityT m a }
  deriving newtype (Functor, Applicative, Monad)
  deriving newtype (MonadTrans, MonadTransControl)

runCustomT :: CustomT m a -> m a
runCustomT = runIdentityT . unCustomT

Now you want to use this monad transformer in a transformer stack.

newtype StackT m a = StackT { unStackT :: CustomT (ReaderT Bool m) a }
  deriving newtype (Functor, Applicative, Monad)

Unfortunately we can't derive a (Monad m => MonadReader Bool (StackT m)) instance with GeneralizedNewtypeDeriving, without also adding the instance to CustomT.

To still derive this trivial instance we can use Elevator with DerivingVia.

  deriving (MonadReader Bool) via (Elevator CustomT (ReaderT Bool m))

Example 3: Adding an instance for Elevator

Suppose you define a new type class.

class Monad m => MonadCustom m where
  simpleMethod :: a -> m a
  complicatedMethod :: (a -> m b) -> m b

A simple way to allow a type class to be lifted through other monad transformers is by adding an instance for Elevator.

You have to be careful about monadic state StT, when defining such instances using MonadTransControl.

instance (MonadCustom m, MonadTransControl t) => MonadCustom (Elevator t m) where
  simpleMethod = lift . simpleMethod
  complicatedMethod f = (restoreT . pure =<<) $ liftWith $ \ runT ->
    complicatedMethod $ runT . f

Some useful examples (or exercises) are the instances for mtl's type classes (MonadError, MonadReader, MonadState, MonadWriter).