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

Copyright | Bas van Dijk, Anders Kaseorg
License | BSD-style
Maintainer | Bas van Dijk <v.dijk.bas@gmail.com>
Stability | experimental
Safe Haskell | Safe
Language | Haskell98

Control.Monad.Trans.Control

Contents

- MonadTransControl
  - Defaults
- MonadBaseControl
  - Defaults
- Utility functions

Description

Synopsis

- class MonadTrans t => MonadTransControl t where
  - type StT t a :: *
- type Run t = forall n b. Monad n => t n b -> n (StT t b)
- type RunDefault t t' = forall n 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 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
- class MonadBase b m => MonadBaseControl b m | m -> b where
  - type StM m a :: *
- type RunInBase m b = forall a. m a -> b (StM m a)
- type ComposeSt t m a = StM m (StT t a)
- type RunInBaseDefault t m b = forall a. t m a -> b (ComposeSt t m a)
- defaultLiftBaseWith :: (MonadTransControl t, MonadBaseControl b m) => (RunInBaseDefault t m b -> b a) -> t m a
- defaultRestoreM :: (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
- embed :: MonadBaseControl b m => (a -> m c) -> m (a -> b (StM m c))
- embed_ :: MonadBaseControl b m => (a -> m ()) -> m (a -> b ())
- captureT :: (MonadTransControl t, Monad (t m), Monad m) => t m (StT t ())
- captureM :: 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 where #

Minimal complete definition

liftWith, restoreT

Associated Types

type StT t a :: * #

Monadic state of `t`.

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 . const . return = return

    liftWith (const (m >>= f)) = liftWith (const m) >>= liftWith . const . f

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.

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

Instances

MonadTransControl MaybeT # |
Associated Types type StT (MaybeT :: (* -> *) -> * -> *) a :: * # Methods liftWith :: Monad m => (Run MaybeT -> m a) -> MaybeT m a # restoreT :: Monad m => m (StT MaybeT a) -> MaybeT m a #
MonadTransControl ListT # |
Associated Types type StT (ListT :: (* -> *) -> * -> *) a :: * # Methods liftWith :: Monad m => (Run ListT -> m a) -> ListT m a # restoreT :: Monad m => m (StT ListT a) -> ListT m a #
Monoid w => MonadTransControl (WriterT w) # |
Associated Types type StT (WriterT w :: (* -> *) -> * -> *) a :: * # 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) # |
Associated Types type StT (WriterT w :: (* -> *) -> * -> *) a :: * # 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 #
MonadTransControl (StateT s) # |
Associated Types type StT (StateT s :: (* -> *) -> * -> *) a :: * # 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) # |
Associated Types type StT (StateT s :: (* -> *) -> * -> *) a :: * # 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 (IdentityT *) # |
Associated Types type StT (IdentityT * :: (* -> *) -> * -> *) a :: * # Methods liftWith :: Monad m => (Run (IdentityT *) -> m a) -> IdentityT * m a # restoreT :: Monad m => m (StT (IdentityT *) a) -> IdentityT * m a #
Error e => MonadTransControl (ErrorT e) # |
Associated Types type StT (ErrorT e :: (* -> *) -> * -> *) a :: * # Methods liftWith :: Monad m => (Run (ErrorT e) -> m a) -> ErrorT e m a # restoreT :: Monad m => m (StT (ErrorT e) a) -> ErrorT e m a #
MonadTransControl (ExceptT e) # |
Associated Types type StT (ExceptT e :: (* -> *) -> * -> *) a :: * # 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 (ReaderT * r) # |
Associated Types type StT (ReaderT * r :: (* -> *) -> * -> *) a :: * # 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 #
Monoid w => MonadTransControl (RWST r w s) # |
Associated Types type StT (RWST r w s :: (* -> *) -> * -> *) a :: * # 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) # |
Associated Types type StT (RWST r w s :: (* -> *) -> * -> *) a :: * # 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 = forall n 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`.

## Defaults

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

    {-# LANGUAGE GeneralizedNewtypeDeriving #-}

    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 t' = forall n 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 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.

# MonadBaseControl

class MonadBase b m => MonadBaseControl b m | m -> b where #

Minimal complete definition

liftBaseWith, restoreM

Associated Types

type StM m a :: * #

Monadic state of `m`.

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 . const . return = return

    liftBaseWith (const (m >>= f)) = liftBaseWith (const m) >>= liftBaseWith . const . f

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.

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

Instances

MonadBaseControl [] [] # |
Associated Types type StM ([] :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase [] [] -> [a]) -> [a] # restoreM :: StM [] a -> [a] #
MonadBaseControl Maybe Maybe # |
Associated Types type StM (Maybe :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase Maybe Maybe -> Maybe a) -> Maybe a # restoreM :: StM Maybe a -> Maybe a #
MonadBaseControl IO IO # |
Associated Types type StM (IO :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase IO IO -> IO a) -> IO a # restoreM :: StM IO a -> IO a #
MonadBaseControl Identity Identity # |
Associated Types type StM (Identity :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase Identity Identity -> Identity a) -> Identity a # restoreM :: StM Identity a -> Identity a #
MonadBaseControl STM STM # |
Associated Types type StM (STM :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase STM STM -> STM a) -> STM a # restoreM :: StM STM a -> STM a #
MonadBaseControl b m => MonadBaseControl b (ListT m) # |
Associated Types type StM (ListT m :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase (ListT m) b -> b a) -> ListT m a # restoreM :: StM (ListT m) a -> ListT m a #
MonadBaseControl b m => MonadBaseControl b (MaybeT m) # |
Associated Types type StM (MaybeT m :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase (MaybeT m) b -> b a) -> MaybeT m a # restoreM :: StM (MaybeT m) a -> MaybeT m a #
(Monoid w, MonadBaseControl b m) => MonadBaseControl b (WriterT w m) # |
Associated Types type StM (WriterT w m :: * -> *) a :: * # 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) # |
Associated Types type StM (WriterT w m :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase (WriterT w m) b -> b a) -> WriterT w m a # restoreM :: StM (WriterT w m) a -> WriterT w m a #
(Error e, MonadBaseControl b m) => MonadBaseControl b (ErrorT e m) # |
Associated Types type StM (ErrorT e m :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase (ErrorT e m) b -> b a) -> ErrorT e m a # restoreM :: StM (ErrorT e m) a -> ErrorT e m a #
MonadBaseControl b m => MonadBaseControl b (ExceptT e m) # |
Associated Types type StM (ExceptT e m :: * -> *) a :: * # 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 (StateT s m) # |
Associated Types type StM (StateT s m :: * -> *) a :: * # 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) # |
Associated Types type StM (StateT s m :: * -> *) a :: * # 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 (IdentityT * m) # |
Associated Types type StM (IdentityT * m :: * -> *) a :: * # 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) # |
Associated Types type StM (ReaderT * r m :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase (ReaderT * r m) b -> b a) -> ReaderT * r m a # restoreM :: StM (ReaderT * r m) a -> ReaderT * r m a #
(Monoid w, MonadBaseControl b m) => MonadBaseControl b (RWST r w s m) # |
Associated Types type StM (RWST r w s m :: * -> *) a :: * # 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) # |
Associated Types type StM (RWST r w s m :: * -> *) a :: * # 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 ((->) r) ((->) r) # |
Associated Types type StM ((->) r :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase ((->) r) ((->) r) -> r -> a) -> r -> a # restoreM :: StM ((->) r) a -> r -> a #
MonadBaseControl (Either e) (Either e) # |
Associated Types type StM (Either e :: * -> *) a :: * # 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) # |
Associated Types type StM (ST s :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase (ST s) (ST s) -> ST s a) -> ST s a # restoreM :: StM (ST s) a -> ST s a #
MonadBaseControl (ST s) (ST s) # |
Associated Types type StM (ST s :: * -> *) a :: * # Methods liftBaseWith :: (RunInBase (ST s) (ST s) -> ST s a) -> ST s a # restoreM :: StM (ST s) a -> ST s a #

type RunInBase m b = 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`.

## 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 m 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 m b = 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 :: (MonadTransControl t, MonadBaseControl b m) => (RunInBaseDefault t m b -> b a) -> t m a #

Default defintion 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 :: (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``

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 :: (MonadTransControl t, Monad (t m), Monad m) => t m (StT t ()) #

Capture the current state of a transformer

captureM :: 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 :: 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 #

Arguments

:: (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`