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

Control.Monad.Trans.Compose

Synopsis

ComposeT

ComposeT can be used in monad transformer stacks to derive instances.

This also allows the usage of these instances, while in the middle of the transformer stack. This proves particularly useful, when writing a runner for a transformer stack.

newtype ComposeT t1 t2 m a Source #

A newtype wrapper for two stacked monad transformers.

Access instances of the intermediate monad (t2 m), whenever t1 implements MonadTrans / MonadTransControl / MonadTransControlIdentity.

Type level arguments:

t1 :: (Type -> Type) -> Type -> Type
outer monad transformer
t2 :: (Type -> Type) -> Type -> Type
inner monad transformer
m :: Type -> Type
monad
a :: Type
value

Constructors

ComposeT 

Fields

Instances

Instances details
(Monad (t2 m), Monoid w) => MonadRWS r w s (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

(Monad (t2 m), Monoid w) => MonadRWS r w s (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

(Monad (t1 (t2 m)), MonadTransControl t1, MonadRWS r w s (t2 m)) => MonadRWS r w s (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

(Monad (t1 (t2 m)), MonadTransControl (ComposeT t1 t2), MonadBaseControl b m) => MonadBaseControl b (ComposeT t1 t2 m) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Associated Types

type StM (ComposeT t1 t2 m) a #

Methods

liftBaseWith :: (RunInBase (ComposeT t1 t2 m) b -> b a) -> ComposeT t1 t2 m a #

restoreM :: StM (ComposeT t1 t2 m) a -> ComposeT t1 t2 m a #

(Monad (t1 (t2 m)), MonadTransControlIdentity (ComposeT t1 t2), MonadBaseControlIdentity b m) => MonadBaseControlIdentity b (ComposeT t1 t2 m) Source #

Elevated to m.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

liftBaseWithIdentity :: ((forall x. ComposeT t1 t2 m x -> b x) -> b a) -> ComposeT t1 t2 m a #

Monad (t2 m) => MonadError e (ComposeT (ExceptT e) t2 m) Source #

Set by ExceptT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

throwError :: e -> ComposeT (ExceptT e) t2 m a #

catchError :: ComposeT (ExceptT e) t2 m a -> (e -> ComposeT (ExceptT e) t2 m a) -> ComposeT (ExceptT e) t2 m a #

(Monad (t1 (t2 m)), MonadTransControl t1, MonadError e (t2 m)) => MonadError e (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

Methods

throwError :: e -> ComposeT t1 t2 m a #

catchError :: ComposeT t1 t2 m a -> (e -> ComposeT t1 t2 m a) -> ComposeT t1 t2 m a #

(Monad (t2 m), Monoid w) => MonadReader r (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

ask :: ComposeT (RWST r w s) t2 m r #

local :: (r -> r) -> ComposeT (RWST r w s) t2 m a -> ComposeT (RWST r w s) t2 m a #

reader :: (r -> a) -> ComposeT (RWST r w s) t2 m a #

(Monad (t2 m), Monoid w) => MonadReader r (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

ask :: ComposeT (RWST r w s) t2 m r #

local :: (r -> r) -> ComposeT (RWST r w s) t2 m a -> ComposeT (RWST r w s) t2 m a #

reader :: (r -> a) -> ComposeT (RWST r w s) t2 m a #

Monad (t2 m) => MonadReader r (ComposeT (ReaderT r) t2 m) Source #

Set by ReaderT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

ask :: ComposeT (ReaderT r) t2 m r #

local :: (r -> r) -> ComposeT (ReaderT r) t2 m a -> ComposeT (ReaderT r) t2 m a #

reader :: (r -> a) -> ComposeT (ReaderT r) t2 m a #

(Monad (t1 (t2 m)), MonadTransControl t1, MonadReader r (t2 m)) => MonadReader r (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

Methods

ask :: ComposeT t1 t2 m r #

local :: (r -> r) -> ComposeT t1 t2 m a -> ComposeT t1 t2 m a #

reader :: (r -> a) -> ComposeT t1 t2 m a #

(Monad (t2 m), Monoid w) => MonadState s (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

get :: ComposeT (RWST r w s) t2 m s #

put :: s -> ComposeT (RWST r w s) t2 m () #

state :: (s -> (a, s)) -> ComposeT (RWST r w s) t2 m a #

(Monad (t2 m), Monoid w) => MonadState s (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

get :: ComposeT (RWST r w s) t2 m s #

put :: s -> ComposeT (RWST r w s) t2 m () #

state :: (s -> (a, s)) -> ComposeT (RWST r w s) t2 m a #

Monad (t2 m) => MonadState s (ComposeT (StateT s) t2 m) Source #

Set by StateT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

get :: ComposeT (StateT s) t2 m s #

put :: s -> ComposeT (StateT s) t2 m () #

state :: (s -> (a, s)) -> ComposeT (StateT s) t2 m a #

Monad (t2 m) => MonadState s (ComposeT (StateT s) t2 m) Source #

Set by StateT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

get :: ComposeT (StateT s) t2 m s #

put :: s -> ComposeT (StateT s) t2 m () #

state :: (s -> (a, s)) -> ComposeT (StateT s) t2 m a #

(Monad (t1 (t2 m)), MonadTrans t1, MonadState s (t2 m)) => MonadState s (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

Methods

get :: ComposeT t1 t2 m s #

put :: s -> ComposeT t1 t2 m () #

state :: (s -> (a, s)) -> ComposeT t1 t2 m a #

(Monad (t2 m), Monoid w) => MonadWriter w (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

writer :: (a, w) -> ComposeT (RWST r w s) t2 m a #

tell :: w -> ComposeT (RWST r w s) t2 m () #

listen :: ComposeT (RWST r w s) t2 m a -> ComposeT (RWST r w s) t2 m (a, w) #

pass :: ComposeT (RWST r w s) t2 m (a, w -> w) -> ComposeT (RWST r w s) t2 m a #

(Monad (t2 m), Monoid w) => MonadWriter w (ComposeT (RWST r w s) t2 m) Source #

Set by RWST.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

writer :: (a, w) -> ComposeT (RWST r w s) t2 m a #

tell :: w -> ComposeT (RWST r w s) t2 m () #

listen :: ComposeT (RWST r w s) t2 m a -> ComposeT (RWST r w s) t2 m (a, w) #

pass :: ComposeT (RWST r w s) t2 m (a, w -> w) -> ComposeT (RWST r w s) t2 m a #

(Monad (t2 m), Monoid w) => MonadWriter w (ComposeT (WriterT w) t2 m) Source #

Set by WriterT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

writer :: (a, w) -> ComposeT (WriterT w) t2 m a #

tell :: w -> ComposeT (WriterT w) t2 m () #

listen :: ComposeT (WriterT w) t2 m a -> ComposeT (WriterT w) t2 m (a, w) #

pass :: ComposeT (WriterT w) t2 m (a, w -> w) -> ComposeT (WriterT w) t2 m a #

(Monad (t2 m), Monoid w) => MonadWriter w (ComposeT (WriterT w) t2 m) Source #

Set by WriterT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

writer :: (a, w) -> ComposeT (WriterT w) t2 m a #

tell :: w -> ComposeT (WriterT w) t2 m () #

listen :: ComposeT (WriterT w) t2 m a -> ComposeT (WriterT w) t2 m (a, w) #

pass :: ComposeT (WriterT w) t2 m (a, w -> w) -> ComposeT (WriterT w) t2 m a #

(Monad (t1 (t2 m)), MonadTransControl t1, MonadWriter w (t2 m)) => MonadWriter w (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

Methods

writer :: (a, w) -> ComposeT t1 t2 m a #

tell :: w -> ComposeT t1 t2 m () #

listen :: ComposeT t1 t2 m a -> ComposeT t1 t2 m (a, w) #

pass :: ComposeT t1 t2 m (a, w -> w) -> ComposeT t1 t2 m a #

(Monad (t1 (t2 m)), MonadTrans (ComposeT t1 t2), MonadBase b m) => MonadBase b (ComposeT t1 t2 m) Source #

Elevated to m.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

liftBase :: b α -> ComposeT t1 t2 m α #

(forall (m :: Type -> Type). Monad m => Monad (t2 m), MonadTransControl t1, MonadTransControl t2) => MonadTransControl (ComposeT t1 t2) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Associated Types

type StT (ComposeT t1 t2) a #

Methods

liftWith :: Monad m => (Run (ComposeT t1 t2) -> m a) -> ComposeT t1 t2 m a #

restoreT :: Monad m => m (StT (ComposeT t1 t2) a) -> ComposeT t1 t2 m a #

(forall (m :: Type -> Type). Monad m => Monad (t2 m), MonadTransControlIdentity t1, MonadTransControlIdentity t2) => MonadTransControlIdentity (ComposeT t1 t2) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Methods

liftWithIdentity :: Monad m => ((forall x. ComposeT t1 t2 m x -> m x) -> m a) -> ComposeT t1 t2 m a #

(forall (m :: Type -> Type). Monad m => Monad (t2 m), MonadTrans t1, MonadTrans t2) => MonadTrans (ComposeT t1 t2) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Methods

lift :: Monad m => m a -> ComposeT t1 t2 m a #

(Monad (t1 (t2 m)), MonadTrans (ComposeT t1 t2), MonadIO m) => MonadIO (ComposeT t1 t2 m) Source #

Elevated to m.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

liftIO :: IO a -> ComposeT t1 t2 m a #

Applicative (t1 (t2 m)) => Applicative (ComposeT t1 t2 m) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Methods

pure :: a -> ComposeT t1 t2 m a #

(<*>) :: ComposeT t1 t2 m (a -> b) -> ComposeT t1 t2 m a -> ComposeT t1 t2 m b #

liftA2 :: (a -> b -> c) -> ComposeT t1 t2 m a -> ComposeT t1 t2 m b -> ComposeT t1 t2 m c #

(*>) :: ComposeT t1 t2 m a -> ComposeT t1 t2 m b -> ComposeT t1 t2 m b #

(<*) :: ComposeT t1 t2 m a -> ComposeT t1 t2 m b -> ComposeT t1 t2 m a #

Functor (t1 (t2 m)) => Functor (ComposeT t1 t2 m) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Methods

fmap :: (a -> b) -> ComposeT t1 t2 m a -> ComposeT t1 t2 m b #

(<$) :: a -> ComposeT t1 t2 m b -> ComposeT t1 t2 m a #

Monad (t1 (t2 m)) => Monad (ComposeT t1 t2 m) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Methods

(>>=) :: ComposeT t1 t2 m a -> (a -> ComposeT t1 t2 m b) -> ComposeT t1 t2 m b #

(>>) :: ComposeT t1 t2 m a -> ComposeT t1 t2 m b -> ComposeT t1 t2 m b #

return :: a -> ComposeT t1 t2 m a #

Monad (t2 m) => MonadCatch (ComposeT CatchT t2 m) Source #

Set by CatchT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

catch :: Exception e => ComposeT CatchT t2 m a -> (e -> ComposeT CatchT t2 m a) -> ComposeT CatchT t2 m a #

(Monad (t1 (t2 m)), MonadTransControl t1, MonadCatch (t2 m)) => MonadCatch (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

Methods

catch :: Exception e => ComposeT t1 t2 m a -> (e -> ComposeT t1 t2 m a) -> ComposeT t1 t2 m a #

Monad (t2 m) => MonadThrow (ComposeT CatchT t2 m) Source #

Set by CatchT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

throwM :: Exception e => e -> ComposeT CatchT t2 m a #

(Monad (t1 (t2 m)), MonadTrans t1, MonadThrow (t2 m)) => MonadThrow (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

Methods

throwM :: Exception e => e -> ComposeT t1 t2 m a #

Monad (t2 m) => MonadCont (ComposeT (ContT r) t2 m) Source #

Set by ContT.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

callCC :: ((a -> ComposeT (ContT r) t2 m b) -> ComposeT (ContT r) t2 m a) -> ComposeT (ContT r) t2 m a #

(Monad (t1 (t2 m)), MonadTransControl t1, MonadCont (t2 m)) => MonadCont (ComposeT t1 t2 m) Source #

OVERLAPPABLE. Elevated to (t2 m).

Instance details

Defined in Control.Monad.Trans.Compose

Methods

callCC :: ((a -> ComposeT t1 t2 m b) -> ComposeT t1 t2 m a) -> ComposeT t1 t2 m a #

(Monad (t1 (t2 m)), MonadTrans (ComposeT t1 t2), PrimMonad m) => PrimMonad (ComposeT t1 t2 m) Source # 
Instance details

Defined in Control.Monad.Trans.Compose

Associated Types

type PrimState (ComposeT t1 t2 m) #

Methods

primitive :: (State# (PrimState (ComposeT t1 t2 m)) -> (# State# (PrimState (ComposeT t1 t2 m)), a #)) -> ComposeT t1 t2 m a #

(Monad (t1 (t2 m)), MonadTransControlIdentity (ComposeT t1 t2), MonadUnliftIO m) => MonadUnliftIO (ComposeT t1 t2 m) Source #

Elevated to m.

Instance details

Defined in Control.Monad.Trans.Compose

Methods

withRunInIO :: ((forall a. ComposeT t1 t2 m a -> IO a) -> IO b) -> ComposeT t1 t2 m b #

type StT (ComposeT t1 t2) a Source # 
Instance details

Defined in Control.Monad.Trans.Compose

type StT (ComposeT t1 t2) a = StT t2 (StT t1 a)
type PrimState (ComposeT t1 t2 m) Source #

Elevated to m.

Instance details

Defined in Control.Monad.Trans.Compose

type PrimState (ComposeT t1 t2 m) = PrimState (Elevator (ComposeT t1 t2) m)
type StM (ComposeT t1 t2 m) a Source #

Elevated to m.

Instance details

Defined in Control.Monad.Trans.Compose

type StM (ComposeT t1 t2 m) a = StM (Elevator (ComposeT t1 t2) m) a

Run ComposeT

You have to run the composed monad transformers to get back into the base monad at some point.

runComposeT Source #

Arguments

:: (forall a. t1 (t2 m) a -> t2 m (StT t1 a))

run t1

-> (forall a. t2 m a -> m (StT t2 a))

run t2

-> forall a. ComposeT t1 t2 m a -> m (StT t2 (StT t1 a)) 

Run two stacked monad transformers.

This function takes the two individual monad transformer runners as arguments.

runComposeT' Source #

Arguments

:: (t1 (t2 m) a -> t2 m a)

run t1

-> (t2 m a -> m a)

run t2

-> ComposeT t1 t2 m a -> m a 

Equivalent to runComposeT, but discards the monadic state StT. This is a simple approach when your monad transformer stack doesn't carry monadic state.

StT (ComposeT t1 t2) a ~ a

This can be used to improve error messages when modifying a monad transformer stack.

Examples

Example 1: Create a new type class

When creating a new type class that supports ComposeT, you want to add recursive instances for ComposeT.

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

You can easily derive those instances, after implementing an instance for Elevator. This is explained in Control.Monad.Trans.Elevator.

Then it's possible to derive the recursive instance. This is an OVERLAPPABLE instance, because we want to be able to add new "base-case" instances through transformers in a stack.

deriving via Elevator t1 (t2 (m :: * -> *))
  instance {-# OVERLAPPABLE #-}
    ( Monad (t1 (t2 m))
    , MonadTransControl t1
    , MonadCustom (t2 m)
    ) => MonadCustom (ComposeT t1 t2 m)

Example 2: Add an instance

Add a type class instance for a new monad transformer, when there already is a recursive instance for ComposeT.

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

First we need the regular instance. The method implementations are undefined here, because they would only distract from ComposeT.

instance Monad m => MonadCustom (CustomT m) where
  simpleMethod = undefined
  complicatedMethod = undefined

To add a "base-case" instance, that takes priority over the recursive instance, FlexibleInstances are required.

deriving via CustomT (t2 (m :: * -> *))
  instance Monad (t2 m) => MonadCustom (ComposeT CustomT t2 m)

Example 3: Build a transformer stack

Create a monad transformer stack and wrap it using a newtype.

type AppStackT = TransparentT .|> ReaderT Bool .|> CustomT .|> ReaderT Char .|> StateT Int
newtype AppT m a = AppT { unAppT :: AppStackT m a }
  deriving newtype (Functor, Applicative, Monad)

Using .|> we can write AppStackT in the order of initialization. We are adding TransparentT to the bottom of the stack, so that all the other transformer instances actually end up in the stack. Now we can simply derive just the instances, that we want.

  deriving newtype (MonadTrans, MonadTransControl)
  deriving newtype (MonadState Int)
  deriving newtype MonadCustom

We can even access instances, that would have been shadowed in a regular transformer stack.

  deriving newtype (MonadReader Bool)

Example 4: Run a transformer stack

This is the part, that actually contains your application logic. Because of the setup with ComposeT, we won't have to worry about lifting during the initialization. With ..> we can use the order of initialization again.

runAppT :: AppT m a -> m (StT AppT a)
runAppT appTma =
  runTransparentT
    ./> (\ tma -> runReaderT tma True)
    ./> runCustomT
    ./> runReaderT'
    ./> runStateT'
    $ unAppT appTma
 where
  runReaderT' :: MonadReader Bool m => ReaderT Char m a -> m a
  runReaderT' tma = do
    bool <- ask
    let char = if bool then 'Y' else 'N'
    runReaderT tma char

  runStateT' :: MonadReader Char m => StateT Int m a -> m (a, Int)
  runStateT' tma = do
    char <- ask
    let num = fromEnum char
    runStateT tma num