Control.Monad.Trans.Control

monad-control-1.0.3.1: Lift control operations, like exception catching, through monad transformers

Copyright | Bas van Dijk Anders Kaseorg
License | BSD3
Maintainer | Bas van Dijk <v.dijk.bas@gmail.com>
Safe Haskell | Safe
Language | Haskell2010

Control.Monad.Trans.Control

Contents

- MonadTransControl
  - Defaults
    - Defaults for a stack of two
- MonadBaseControl
  - Defaults
- Utility functions

Description

This module defines the type class `MonadBaseControl`, a subset of `MonadBase` into which generic control operations such as `catch` can be lifted from `IO` or any other base monad. Instances are based on monad transformers in `MonadTransControl`, which includes all standard monad transformers in the `transformers` library except `ContT`.

See the lifted-base package which uses `monad-control` to lift `IO` operations from the `base` library (like `catch` or `bracket`) into any monad that is an instance of `MonadBase` or `MonadBaseControl`.

See the following tutorial by Michael Snoyman on how to use this package:

https://www.yesodweb.com/book/monad-control

### Quick implementation guide

Given a base monad `B` and a stack of transformers `T`:

- Define instances ``MonadTransControl` T` for all transformers `T`, using the ``defaultLiftWith`` and ``defaultRestoreT`` functions on the constructor and deconstructor of `T`.

- Define an instance ``MonadBaseControl` B B` for the base monad:

      instance MonadBaseControl B B where
          type StM B a   = a
          liftBaseWith f = f id
          restoreM       = return

- Define instances ``MonadBaseControl` B m => `MonadBaseControl` B (T m)` for all transformers:

      instance MonadBaseControl b m => MonadBaseControl b (T m) where
          type StM (T m) a = ComposeSt T m a
          liftBaseWith f   = defaultLiftBaseWith
          restoreM         = defaultRestoreM

Synopsis

- class MonadTrans t => MonadTransControl (t :: (Type -> Type) -> Type -> Type) where
  - type StT (t :: (Type -> Type) -> Type -> Type) a
  - liftWith :: Monad m => (Run t -> m a) -> t m a
  - restoreT :: Monad m => m (StT t a) -> t m a
- type Run (t :: (Type -> Type) -> Type -> Type) = forall (n :: Type -> Type) b. Monad n => t n b -> n (StT t b)
- type RunDefault (t :: (Type -> Type) -> Type -> Type) (t' :: (Type -> Type) -> Type -> Type) = forall (n :: Type -> Type) b. Monad n => t n b -> n (StT t' b)
- defaultLiftWith :: (Monad m, MonadTransControl n) => (forall b. n m b -> t m b) -> (forall (o :: Type -> Type) b. t o b -> n o b) -> (RunDefault t n -> m a) -> t m a
- defaultRestoreT :: (Monad m, MonadTransControl n) => (n m a -> t m a) -> m (StT n a) -> t m a
- type RunDefault2 (t :: (Type -> Type) -> Type -> Type) (n :: (Type -> Type) -> Type -> Type) (n' :: (Type -> Type) -> Type -> Type) = forall (m :: Type -> Type) b. (Monad m, Monad (n' m)) => t m b -> m (StT n' (StT n b))
- defaultLiftWith2 :: forall m (n' :: (Type -> Type) -> Type -> Type) n t a. (Monad m, Monad (n' m), MonadTransControl n, MonadTransControl n') => (forall b. n (n' m) b -> t m b) -> (forall (o :: Type -> Type) b. t o b -> n (n' o) b) -> (RunDefault2 t n n' -> m a) -> t m a
- defaultRestoreT2 :: forall m (n' :: (Type -> Type) -> Type -> Type) n a t. (Monad m, Monad (n' m), MonadTransControl n, MonadTransControl n') => (n (n' m) a -> t m a) -> m (StT n' (StT n a)) -> t m a
- class MonadBase b m => MonadBaseControl (b :: Type -> Type) (m :: Type -> Type) | m -> b where
  - type StM (m :: Type -> Type) a
  - liftBaseWith :: (RunInBase m b -> b a) -> m a
  - restoreM :: StM m a -> m a
- type RunInBase (m :: Type -> Type) (b :: Type -> Type) = forall a. m a -> b (StM m a)
- type ComposeSt (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a = StM m (StT t a)
- type RunInBaseDefault (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (b :: Type -> Type) = forall a. t m a -> b (ComposeSt t m a)
- defaultLiftBaseWith :: forall t b (m :: Type -> Type) a. (MonadTransControl t, MonadBaseControl b m) => (RunInBaseDefault t m b -> b a) -> t m a
- defaultRestoreM :: forall t (b :: Type -> Type) (m :: Type -> Type) a. (MonadTransControl t, MonadBaseControl b m) => ComposeSt t m a -> t m a
- control :: MonadBaseControl b m => (RunInBase m b -> b (StM m a)) -> m a
- controlT :: (MonadTransControl t, Monad (t m), Monad m) => (Run t -> m (StT t a)) -> t m a
- embed :: MonadBaseControl b m => (a -> m c) -> m (a -> b (StM m c))
- embed_ :: MonadBaseControl b m => (a -> m ()) -> m (a -> b ())
- captureT :: forall t (m :: Type -> Type). (MonadTransControl t, Monad (t m), Monad m) => t m (StT t ())
- captureM :: forall (b :: Type -> Type) m. MonadBaseControl b m => m (StM m ())
- liftBaseOp :: MonadBaseControl b m => ((a -> b (StM m c)) -> b (StM m d)) -> (a -> m c) -> m d
- liftBaseOp_ :: MonadBaseControl b m => (b (StM m a) -> b (StM m c)) -> m a -> m c
- liftBaseDiscard :: MonadBaseControl b m => (b () -> b a) -> m () -> m a
- liftBaseOpDiscard :: MonadBaseControl b m => ((a -> b ()) -> b c) -> (a -> m ()) -> m c
- liftThrough :: (MonadTransControl t, Monad (t m), Monad m) => (m (StT t a) -> m (StT t b)) -> t m a -> t m b

# MonadTransControl

class MonadTrans t => MonadTransControl (t :: (Type -> Type) -> Type -> Type) where #

The `MonadTransControl` type class is a stronger version of ``MonadTrans``:

Instances of ``MonadTrans`` know how to ``lift`` actions in the base monad to the transformed monad. These lifted actions, however, are completely unaware of the monadic state added by the transformer.

``MonadTransControl`` instances are aware of the monadic state of the transformer and allow to save and restore this state.

This allows to lift functions that have a monad transformer in both positive and negative position. Take, for example, the function

    withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r

``MonadTrans`` instances can only lift the return type of the `withFile` function:

    withFileLifted :: MonadTrans t => FilePath -> IOMode -> (Handle -> IO r) -> t IO r
    withFileLifted file mode action = lift (withFile file mode action)

However, ``MonadTrans`` is not powerful enough to make `withFileLifted` accept a function that returns `t IO`. The reason is that we need to take away the transformer layer in order to pass the function to ``withFile``. ``MonadTransControl`` allows us to do this:

    withFileLifted' :: (Monad (t IO), MonadTransControl t) => FilePath -> IOMode -> (Handle -> t IO r) -> t IO r
    withFileLifted' file mode action = liftWith (\run -> withFile file mode (run . action)) >>= restoreT . return

Associated Types

type StT (t :: (Type -> Type) -> Type -> Type) a #

Monadic state of `t`.

The monadic state of a monad transformer is the result type of its `run` function, e.g.:

    runReaderT :: ReaderT r m a -> r -> m a
    StT (ReaderT r) a ~ a

    runStateT :: StateT s m a -> s -> m (a, s)
    StT (StateT s) a ~ (a, s)

    runMaybeT :: MaybeT m a -> m (Maybe a)
    StT MaybeT a ~ Maybe a

Provided type instances:

    StT IdentityT    a ~ a
    StT MaybeT       a ~ Maybe a
    StT (ErrorT e)   a ~ Error e => Either e a
    StT (ExceptT e)  a ~ Either e a
    StT ListT        a ~ [a]
    StT (ReaderT r)  a ~ a
    StT (StateT s)   a ~ (a, s)
    StT (WriterT w)  a ~ Monoid w => (a, w)
    StT (RWST r w s) a ~ Monoid w => (a, s, w)

Methods

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

`liftWith` is similar to `lift` in that it lifts a computation from the argument monad to the constructed monad.

Instances should satisfy similar laws as the `MonadTrans` laws:

    liftWith (\_ -> return a) = return a

    liftWith (\_ -> m >>= f)  =  liftWith (\_ -> m) >>= (\a -> liftWith (\_ -> f a))

The difference with `lift` is that before lifting the `m` computation `liftWith` captures the state of `t`. It then provides the `m` computation with a `Run` function that allows running `t n` computations in `n` (for all `n`) on the captured state, e.g.

    withFileLifted :: (Monad (t IO), MonadTransControl t) => FilePath -> IOMode -> (Handle -> t IO r) -> t IO r
    withFileLifted file mode action = liftWith (\run -> withFile file mode (run . action)) >>= restoreT . return

If the `Run` function is ignored, `liftWith` coincides with `lift`:

    lift f = liftWith (\_ -> f)

Implementations use the ``Run`` function associated with a transformer:

    liftWith :: Monad m => ((Monad n => ReaderT r n b -> n b) -> m a) -> ReaderT r m a
    liftWith f = ReaderT (\r -> f (\action -> runReaderT action r))

    liftWith :: Monad m => ((Monad n => StateT s n b -> n (b, s)) -> m a) -> StateT s m a
    liftWith f = StateT (\s -> liftM (\x -> (x, s)) (f (\action -> runStateT action s)))

    liftWith :: Monad m => ((Monad n => MaybeT n b -> n (Maybe b)) -> m a) -> MaybeT m a
    liftWith f = MaybeT (liftM Just (f runMaybeT))

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

Construct a `t` computation from the monadic state of `t` that is returned from a `Run` function.

Instances should satisfy:

    liftWith (\run -> run t) >>= restoreT . return = t

`restoreT` is usually implemented through the constructor of the monad transformer:

    ReaderT  :: (r -> m a) -> ReaderT r m a
    restoreT ::       m a  -> ReaderT r m a
    restoreT action = ReaderT { runReaderT = const action }

    StateT   :: (s -> m (a, s)) -> StateT s m a
    restoreT ::       m (a, s)  -> StateT s m a
    restoreT action = StateT { runStateT = const action }

    MaybeT   :: m (Maybe a) -> MaybeT m a
    restoreT :: m (Maybe a) -> MaybeT m a
    restoreT action = MaybeT action

Example type signatures:

    restoreT :: Monad m             => m a            -> IdentityT m a
    restoreT :: Monad m             => m (Maybe a)    -> MaybeT m a
    restoreT :: (Monad m, Error e)  => m (Either e a) -> ErrorT e m a
    restoreT :: Monad m             => m (Either e a) -> ExceptT e m a
    restoreT :: Monad m             => m [a]          -> ListT m a
    restoreT :: Monad m             => m a            -> ReaderT r m a
    restoreT :: Monad m             => m (a, s)       -> StateT s m a
    restoreT :: (Monad m, Monoid w) => m (a, w)       -> WriterT w m a
    restoreT :: (Monad m, Monoid w) => m (a, s, w)    -> RWST r w s m a

#### Instances

Instances details

MonadTransControl MaybeT # |
Instance details Defined in Control.Monad.Trans.Control Associated Types
type StT MaybeT a |
Instance details Defined in Control.Monad.Trans.Control type StT MaybeT a = Maybe a
Methods liftWith :: Monad m => (Run MaybeT -> m a) -> MaybeT m a # restoreT :: Monad m => m (StT MaybeT a) -> MaybeT m a #
MonadTransControl (ExceptT e) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (ExceptT e) -> m a) -> ExceptT e m a # restoreT :: Monad m => m (StT (ExceptT e) a) -> ExceptT e m a #
MonadTransControl (IdentityT :: (Type -> Type) -> Type -> Type) # |
Instance details Defined in Control.Monad.Trans.Control Associated Types
type StT (IdentityT :: (Type -> Type) -> Type -> Type) a |
Instance details Defined in Control.Monad.Trans.Control type StT (IdentityT :: (Type -> Type) -> Type -> Type) a = a
Methods liftWith :: Monad m => (Run (IdentityT :: (Type -> Type) -> Type -> Type) -> m a) -> IdentityT m a # restoreT :: Monad m => m (StT (IdentityT :: (Type -> Type) -> Type -> Type) a) -> IdentityT m a #
MonadTransControl (ReaderT r) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (ReaderT r) -> m a) -> ReaderT r m a # restoreT :: Monad m => m (StT (ReaderT r) a) -> ReaderT r m a #
MonadTransControl (StateT s) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (StateT s) -> m a) -> StateT s m a # restoreT :: Monad m => m (StT (StateT s) a) -> StateT s m a #
MonadTransControl (StateT s) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (StateT s) -> m a) -> StateT s m a # restoreT :: Monad m => m (StT (StateT s) a) -> StateT s m a #
Monoid w => MonadTransControl (WriterT w) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (WriterT w) -> m a) -> WriterT w m a # restoreT :: Monad m => m (StT (WriterT w) a) -> WriterT w m a #
Monoid w => MonadTransControl (WriterT w) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (WriterT w) -> m a) -> WriterT w m a # restoreT :: Monad m => m (StT (WriterT w) a) -> WriterT w m a #
Monoid w => MonadTransControl (RWST r w s) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (RWST r w s) -> m a) -> RWST r w s m a # restoreT :: Monad m => m (StT (RWST r w s) a) -> RWST r w s m a #
Monoid w => MonadTransControl (RWST r w s) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftWith :: Monad m => (Run (RWST r w s) -> m a) -> RWST r w s m a # restoreT :: Monad m => m (StT (RWST r w s) a) -> RWST r w s m a #

type Run (t :: (Type -> Type) -> Type -> Type) = forall (n :: Type -> Type) b. Monad n => t n b -> n (StT t b) #

A function that runs a transformed monad `t n` on the monadic state that was captured by `liftWith`

A `Run t` function yields a computation in `n` that returns the monadic state of `t`. This state can later be used to restore a `t` computation using `restoreT`.

Example type equalities:

    Run IdentityT    ~ forall n b. Monad n             => IdentityT  n b -> n b
    Run MaybeT       ~ forall n b. Monad n             => MaybeT     n b -> n (Maybe b)
    Run (ErrorT e)   ~ forall n b. (Monad n, Error e)  => ErrorT e   n b -> n (Either e b)
    Run (ExceptT e)  ~ forall n b. Monad n             => ExceptT e  n b -> n (Either e b)
    Run ListT        ~ forall n b. Monad n             => ListT      n b -> n [b]
    Run (ReaderT r)  ~ forall n b. Monad n             => ReaderT r  n b -> n b
    Run (StateT s)   ~ forall n b. Monad n             => StateT s   n b -> n (a, s)
    Run (WriterT w)  ~ forall n b. (Monad n, Monoid w) => WriterT w  n b -> n (a, w)
    Run (RWST r w s) ~ forall n b. (Monad n, Monoid w) => RWST r w s n b -> n (a, s, w)

This type is usually satisfied by the `run` function of a transformer:

    flip runReaderT :: r -> Run (ReaderT r)
    flip runStateT  :: s -> Run (StateT s)
    runMaybeT       ::      Run MaybeT

## Defaults

The following functions can be used to define a `MonadTransControl` instance for a monad transformer which simply is a newtype around another monad transformer which already has a `MonadTransControl` instance. For example:

    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE UndecidableInstances #-}
    {-# LANGUAGE TypeFamilies #-}

    newtype CounterT m a = CounterT {unCounterT :: StateT Int m a}
      deriving (Monad, MonadTrans)

    instance MonadTransControl CounterT where
        type StT CounterT a = StT (StateT Int) a
        liftWith = defaultLiftWith CounterT unCounterT
        restoreT = defaultRestoreT CounterT

type RunDefault (t :: (Type -> Type) -> Type -> Type) (t' :: (Type -> Type) -> Type -> Type) = forall (n :: Type -> Type) b. Monad n => t n b -> n (StT t' b) #

A function like `Run` that runs a monad transformer `t` which wraps the monad transformer `t'`. This is used in `defaultLiftWith`.

defaultLiftWith #

Arguments

:: (Monad m, MonadTransControl n) |
=> (forall b. n m b -> t m b) | Monad constructor
-> (forall (o :: Type -> Type) b. t o b -> n o b) | Monad deconstructor
-> (RunDefault t n -> m a) |
-> t m a |

Default definition for the `liftWith` method.

defaultRestoreT #

Arguments

:: (Monad m, MonadTransControl n) |
=> (n m a -> t m a) | Monad constructor
-> m (StT n a) |
-> t m a |

Default definition for the `restoreT` method.

### Defaults for a stack of two

The following functions can be used to define a `MonadTransControl` instance for a monad transformer stack of two.

    {-# LANGUAGE GeneralizedNewtypeDeriving #-}

    newtype CalcT m a = CalcT { unCalcT :: StateT Int (ExceptT String m) a }
      deriving (Monad, MonadTrans)

    instance MonadTransControl CalcT where
        type StT CalcT a = StT (ExceptT String) (StT (StateT Int) a)
        liftWith = defaultLiftWith2 CalcT unCalcT
        restoreT = defaultRestoreT2 CalcT

type RunDefault2 (t :: (Type -> Type) -> Type -> Type) (n :: (Type -> Type) -> Type -> Type) (n' :: (Type -> Type) -> Type -> Type) = forall (m :: Type -> Type) b. (Monad m, Monad (n' m)) => t m b -> m (StT n' (StT n b)) #

A function like `Run` that runs a monad transformer `t` which wraps the monad transformers `n` and `n'`. This is used in `defaultLiftWith2`.

defaultLiftWith2 #

Arguments

:: forall m (n' :: (Type -> Type) -> Type -> Type) n t a. (Monad m, Monad (n' m), MonadTransControl n, MonadTransControl n') |
=> (forall b. n (n' m) b -> t m b) | Monad constructor
-> (forall (o :: Type -> Type) b. t o b -> n (n' o) b) | Monad deconstructor
-> (RunDefault2 t n n' -> m a) |
-> t m a |

Default definition for the `liftWith` method.

defaultRestoreT2 #

Arguments

:: forall m (n' :: (Type -> Type) -> Type -> Type) n a t. (Monad m, Monad (n' m), MonadTransControl n, MonadTransControl n') |
=> (n (n' m) a -> t m a) | Monad constructor
-> m (StT n' (StT n a)) |
-> t m a |

Default definition for the `restoreT` method for double `MonadTransControl`.

# MonadBaseControl

class MonadBase b m => MonadBaseControl (b :: Type -> Type) (m :: Type -> Type) | m -> b where #

## Writing instances

The usual way to write a ``MonadBaseControl`` instance for a transformer stack over a base monad `B` is to write an instance `MonadBaseControl B B` for the base monad, and `MonadTransControl T` instances for every transformer `T`. Instances for ``MonadBaseControl`` are then simply implemented using ``ComposeSt``, ``defaultLiftBaseWith``, ``defaultRestoreM``.

Associated Types

type StM (m :: Type -> Type) a #

Monadic state that `m` adds to the base monad `b`.

For all base (non-transformed) monads, `StM m a ~ a`:

    StM IO         a ~ a
    StM Maybe      a ~ a
    StM (Either e) a ~ a
    StM []         a ~ a
    StM ((->) r)   a ~ a
    StM Identity   a ~ a
    StM STM        a ~ a
    StM (ST s)     a ~ a

If `m` is a transformed monad, `m ~ t b`, ``StM`` is the monadic state of the transformer `t` (given by its `StT` from `MonadTransControl`). For a transformer stack, ``StM`` is defined recursively:

    StM (IdentityT  m) a ~ ComposeSt IdentityT m a ~ StM m a
    StM (MaybeT     m) a ~ ComposeSt MaybeT    m a ~ StM m (Maybe a)
    StM (ErrorT e   m) a ~ ComposeSt ErrorT    m a ~ Error e => StM m (Either e a)
    StM (ExceptT e  m) a ~ ComposeSt ExceptT   m a ~ StM m (Either e a)
    StM (ListT      m) a ~ ComposeSt ListT     m a ~ StM m [a]
    StM (ReaderT r  m) a ~ ComposeSt ReaderT   m a ~ StM m a
    StM (StateT s   m) a ~ ComposeSt StateT    m a ~ StM m (a, s)
    StM (WriterT w  m) a ~ ComposeSt WriterT   m a ~ Monoid w => StM m (a, w)
    StM (RWST r w s m) a ~ ComposeSt RWST      m a ~ Monoid w => StM m (a, s, w)

Methods

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

`liftBaseWith` is similar to `liftIO` and `liftBase` in that it lifts a base computation to the constructed monad.

Instances should satisfy similar laws as the `MonadIO` and `MonadBase` laws:

    liftBaseWith (\_ -> return a) = return a

    liftBaseWith (\_ -> m >>= f)  =  liftBaseWith (\_ -> m) >>= (\a -> liftBaseWith (\_ -> f a))

As Li-yao Xia explains, parametricity guarantees that

    f $ liftBaseWith q = liftBaseWith $ runInBase -> f $ q runInBase

The difference with `liftBase` is that before lifting the base computation `liftBaseWith` captures the state of `m`. It then provides the base computation with a `RunInBase` function that allows running `m` computations in the base monad on the captured state:

    withFileLifted :: MonadBaseControl IO m => FilePath -> IOMode -> (Handle -> m a) -> m a
    withFileLifted file mode action = liftBaseWith (\runInBase -> withFile file mode (runInBase . action)) >>= restoreM
                                 -- = control $ \runInBase -> withFile file mode (runInBase . action)
                                 -- = liftBaseOp (withFile file mode) action

``liftBaseWith`` is usually not implemented directly, but using ``defaultLiftBaseWith``.

restoreM :: StM m a -> m a #

Construct a `m` computation from the monadic state of `m` that is returned from a `RunInBase` function.

Instances should satisfy:

    liftBaseWith (\runInBase -> runInBase m) >>= restoreM = m

``restoreM`` is usually not implemented directly, but using ``defaultRestoreM``.

#### Instances

Instances details

MonadBaseControl STM STM # |
Instance details Defined in Control.Monad.Trans.Control Associated Types
type StM STM a |
Instance details Defined in Control.Monad.Trans.Control type StM STM a = a
Methods liftBaseWith :: (RunInBase STM STM -> STM a) -> STM a # restoreM :: StM STM a -> STM a #
MonadBaseControl Identity Identity # |
Instance details Defined in Control.Monad.Trans.Control Associated Types
type StM Identity a |
Instance details Defined in Control.Monad.Trans.Control type StM Identity a = a
Methods liftBaseWith :: (RunInBase Identity Identity -> Identity a) -> Identity a # restoreM :: StM Identity a -> Identity a #
MonadBaseControl IO IO # |
Instance details Defined in Control.Monad.Trans.Control Associated Types
type StM IO a |
Instance details Defined in Control.Monad.Trans.Control type StM IO a = a
Methods liftBaseWith :: (RunInBase IO IO -> IO a) -> IO a # restoreM :: StM IO a -> IO a #
MonadBaseControl Maybe Maybe # |
Instance details Defined in Control.Monad.Trans.Control Associated Types
type StM Maybe a |
Instance details Defined in Control.Monad.Trans.Control type StM Maybe a = a
Methods liftBaseWith :: (RunInBase Maybe Maybe -> Maybe a) -> Maybe a # restoreM :: StM Maybe a -> Maybe a #
MonadBaseControl [] [] # |
Instance details Defined in Control.Monad.Trans.Control Associated Types
type StM [] a |
Instance details Defined in Control.Monad.Trans.Control type StM [] a = a
Methods liftBaseWith :: (RunInBase [] [] -> [a]) -> [a] # restoreM :: StM [] a -> [a] #
MonadBaseControl b m => MonadBaseControl b (MaybeT m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (MaybeT m) b -> b a) -> MaybeT m a # restoreM :: StM (MaybeT m) a -> MaybeT m a #
MonadBaseControl b m => MonadBaseControl b (ExceptT e m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (ExceptT e m) b -> b a) -> ExceptT e m a # restoreM :: StM (ExceptT e m) a -> ExceptT e m a #
MonadBaseControl b m => MonadBaseControl b (IdentityT m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (IdentityT m) b -> b a) -> IdentityT m a # restoreM :: StM (IdentityT m) a -> IdentityT m a #
MonadBaseControl b m => MonadBaseControl b (ReaderT r m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (ReaderT r m) b -> b a) -> ReaderT r m a # restoreM :: StM (ReaderT r m) a -> ReaderT r m a #
MonadBaseControl b m => MonadBaseControl b (StateT s m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (StateT s m) b -> b a) -> StateT s m a # restoreM :: StM (StateT s m) a -> StateT s m a #
MonadBaseControl b m => MonadBaseControl b (StateT s m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (StateT s m) b -> b a) -> StateT s m a # restoreM :: StM (StateT s m) a -> StateT s m a #
(Monoid w, MonadBaseControl b m) => MonadBaseControl b (WriterT w m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (WriterT w m) b -> b a) -> WriterT w m a # restoreM :: StM (WriterT w m) a -> WriterT w m a #
(Monoid w, MonadBaseControl b m) => MonadBaseControl b (WriterT w m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (WriterT w m) b -> b a) -> WriterT w m a # restoreM :: StM (WriterT w m) a -> WriterT w m a #
(Monoid w, MonadBaseControl b m) => MonadBaseControl b (RWST r w s m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (RWST r w s m) b -> b a) -> RWST r w s m a # restoreM :: StM (RWST r w s m) a -> RWST r w s m a #
(Monoid w, MonadBaseControl b m) => MonadBaseControl b (RWST r w s m) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (RWST r w s m) b -> b a) -> RWST r w s m a # restoreM :: StM (RWST r w s m) a -> RWST r w s m a #
MonadBaseControl (ST s) (ST s) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (ST s) (ST s) -> ST s a) -> ST s a # restoreM :: StM (ST s) a -> ST s a #
MonadBaseControl (Either e) (Either e) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (Either e) (Either e) -> Either e a) -> Either e a # restoreM :: StM (Either e) a -> Either e a #
MonadBaseControl (ST s) (ST s) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase (ST s) (ST s) -> ST s a) -> ST s a # restoreM :: StM (ST s) a -> ST s a #
MonadBaseControl ((->) r) ((->) r) # |
Instance details Defined in Control.Monad.Trans.Control Methods liftBaseWith :: (RunInBase ((->) r) ((->) r) -> r -> a) -> r -> a # restoreM :: StM ((->) r) a -> r -> a #

type RunInBase (m :: Type -> Type) (b :: Type -> Type) = forall a. m a -> b (StM m a) #

A function that runs a `m` computation on the monadic state that was captured by `liftBaseWith`

A `RunInBase m` function yields a computation in the base monad of `m` that returns the monadic state of `m`. This state can later be used to restore the `m` computation using `restoreM`.

Example type equalities:

    RunInBase (IdentityT  m) b ~ forall a.             IdentityT  m a -> b (StM m a)
    RunInBase (MaybeT     m) b ~ forall a.             MaybeT     m a -> b (StM m (Maybe a))
    RunInBase (ErrorT e   m) b ~ forall a. Error e =>  ErrorT e   m a -> b (StM m (Either e a))
    RunInBase (ExceptT e  m) b ~ forall a.             ExceptT e  m a -> b (StM m (Either e a))
    RunInBase (ListT      m) b ~ forall a.             ListT      m a -> b (StM m [a])
    RunInBase (ReaderT r  m) b ~ forall a.             ReaderT    m a -> b (StM m a)
    RunInBase (StateT s   m) b ~ forall a.             StateT s   m a -> b (StM m (a, s))
    RunInBase (WriterT w  m) b ~ forall a. Monoid w => WriterT w  m a -> b (StM m (a, w))
    RunInBase (RWST r w s m) b ~ forall a. Monoid w => RWST r w s m a -> b (StM m (a, s, w))

For a transformed base monad `m ~ t b`, `'RunInBase m b' ~ `Run` t`.

## Defaults

Note that by using the following default definitions it's easy to make a monad transformer `T` an instance of `MonadBaseControl`:

    instance MonadBaseControl b m => MonadBaseControl b (T m) where
        type StM (T m) a = ComposeSt T m a
        liftBaseWith     = defaultLiftBaseWith
        restoreM         = defaultRestoreM

Defining an instance for a base monad `B` is equally straightforward:

    instance MonadBaseControl B B where
        type StM B a   = a
        liftBaseWith f = f id
        restoreM       = return

type ComposeSt (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a = StM m (StT t a) #

Handy type synonym that composes the monadic states of `t` and `m`.

It can be used to define the `StM` for new `MonadBaseControl` instances.

type RunInBaseDefault (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (b :: Type -> Type) = forall a. t m a -> b (ComposeSt t m a) #

A function like `RunInBase` that runs a monad transformer `t` in its base monad `b`. It is used in `defaultLiftBaseWith`.

defaultLiftBaseWith :: forall t b (m :: Type -> Type) a. (MonadTransControl t, MonadBaseControl b m) => (RunInBaseDefault t m b -> b a) -> t m a #

Default definition for the `liftBaseWith` method.

Note that it composes a `liftWith` of `t` with a `liftBaseWith` of `m` to give a `liftBaseWith` of `t m`:

    defaultLiftBaseWith = \f -> liftWith $ \run ->
                                  liftBaseWith $ \runInBase ->
                                    f $ runInBase . run

defaultRestoreM :: forall t (b :: Type -> Type) (m :: Type -> Type) a. (MonadTransControl t, MonadBaseControl b m) => ComposeSt t m a -> t m a #

Default definition for the `restoreM` method.

Note that: `defaultRestoreM = `restoreT` . `restoreM``

# Utility functions

control :: MonadBaseControl b m => (RunInBase m b -> b (StM m a)) -> m a #

An often used composition: `control f = `liftBaseWith` f >>= `restoreM``

Example:

    liftedBracket :: MonadBaseControl IO m => m a -> (a -> m b) -> (a -> m c) -> m c
    liftedBracket acquire release action = control $ \runInBase ->
        bracket (runInBase acquire)
                (\saved -> runInBase (restoreM saved >>= release))
                (\saved -> runInBase (restoreM saved >>= action))

controlT :: (MonadTransControl t, Monad (t m), Monad m) => (Run t -> m (StT t a)) -> t m a #

Lift a computation and restore the monadic state immediately: `controlT f = `liftWith` f >>= `restoreT` . return`.

embed :: MonadBaseControl b m => (a -> m c) -> m (a -> b (StM m c)) #

Embed a transformer function as an function in the base monad returning a mutated transformer state.

embed_ :: MonadBaseControl b m => (a -> m ()) -> m (a -> b ()) #

Performs the same function as `embed`, but discards transformer state from the embedded function.

captureT :: forall t (m :: Type -> Type). (MonadTransControl t, Monad (t m), Monad m) => t m (StT t ()) #

Capture the current state of a transformer

captureM :: forall (b :: Type -> Type) m. MonadBaseControl b m => m (StM m ()) #

Capture the current state above the base monad

liftBaseOp :: MonadBaseControl b m => ((a -> b (StM m c)) -> b (StM m d)) -> (a -> m c) -> m d #

`liftBaseOp` is a particular application of `liftBaseWith` that allows lifting control operations of type:

    ((a -> b c) -> b c)

to:

    (MonadBaseControl b m => (a -> m c) -> m c)

For example:

    liftBaseOp alloca :: (Storable a, MonadBaseControl IO m) => (Ptr a -> m c) -> m c

liftBaseOp_ :: MonadBaseControl b m => (b (StM m a) -> b (StM m c)) -> m a -> m c #

`liftBaseOp_` is a particular application of `liftBaseWith` that allows lifting control operations of type:

    (b a -> b a)

to:

    (MonadBaseControl b m => m a -> m a)

For example:

    liftBaseOp_ mask_ :: MonadBaseControl IO m => m a -> m a

liftBaseDiscard :: MonadBaseControl b m => (b () -> b a) -> m () -> m a #

`liftBaseDiscard` is a particular application of `liftBaseWith` that allows lifting control operations of type:

    (b () -> b a)

to:

    (MonadBaseControl b m => m () -> m a)

Note that, while the argument computation `m ()` has access to the captured state, all its side-effects in `m` are discarded. It is run only for its side-effects in the base monad `b`.

For example:

    liftBaseDiscard forkIO :: MonadBaseControl IO m => m () -> m ThreadId

liftBaseOpDiscard :: MonadBaseControl b m => ((a -> b ()) -> b c) -> (a -> m ()) -> m c #

`liftBaseOpDiscard` is a particular application of `liftBaseWith` that allows lifting control operations of type:

    ((a -> b ()) -> b c)

to:

    (MonadBaseControl b m => (a -> m ()) -> m c)

Note that, while the argument computation `m ()` has access to the captured state, all its side-effects in `m` are discarded. It is run only for its side-effects in the base monad `b`.

For example:

    liftBaseDiscard (runServer addr port) :: MonadBaseControl IO m => m () -> m ()

liftThrough :: (MonadTransControl t, Monad (t m), Monad m) => (m (StT t a) -> m (StT t b)) -> t m a -> t m b #

Transform an action in `t m` using a transformer that operates on the underlying monad `m`