| 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.Aligned
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 and SelectT.
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
for all transformersMonadTransControlTT, using theanddefaultLiftWithfunctions on the constructor and deconstructor ofdefaultRestoreTT. Define an instance
for the base monad:MonadBaseControlB Binstance MonadBaseControl B B where type StM B a = a liftBaseWith f = fidrestoreM =returnDefine instances
for all transformers:MonadBaseControlB m =>MonadBaseControlB (T m)instance MonadBaseControl b m => MonadBaseControl b (T m) where type StM (T m) a =ComposeStT m a liftBaseWith f =defaultLiftBaseWithrestoreM =defaultRestoreM
Synopsis
- class MonadTrans t => MonadTransControl t stT | t -> stT where
- type Run t stT = forall n b. Monad n => t n b -> n (stT b)
- type RunDefault t stT = forall n b. Monad n => t n b -> n (stT b)
- defaultLiftWith :: (Monad m, MonadTransControl n stT) => (forall b. n m b -> t m b) -> (forall o b. t o b -> n o b) -> (RunDefault t stT -> m a) -> t m a
- defaultRestoreT :: (Monad m, MonadTransControl n stT) => (n m a -> t m a) -> m (stT a) -> t m a
- class MonadBase b m => MonadBaseControl b m stM | m -> b stM where
- liftBaseWith :: (RunInBase m b stM -> b a) -> m a
- restoreM :: stM a -> m a
- type RunInBase m b stM = forall a. m a -> b (stM a)
- type RunInBaseDefault (t :: (* -> *) -> * -> *) (m :: * -> *) (b :: * -> *) (stM :: * -> *) (stT :: * -> *) = forall a. t m a -> b (Compose stM stT a)
- defaultLiftBaseWith :: (MonadTransControl t stT, MonadBaseControl b m stM) => (RunInBaseDefault t m b stM stT -> b a) -> t m a
- defaultRestoreM :: (MonadTransControl t stT, MonadBaseControl b m stM) => Compose stM stT a -> t m a
- control :: MonadBaseControl b m stM => (RunInBase m b stM -> b (stM a)) -> m a
- controlT :: (MonadTransControl t stT, Monad (t m), Monad m) => (Run t stT -> m (stT a)) -> t m a
- embed :: MonadBaseControl b m stM => (a -> m c) -> m (a -> b (stM c))
- embed_ :: MonadBaseControl b m stM => (a -> m ()) -> m (a -> b ())
- captureT :: (MonadTransControl t stT, Monad (t m), Monad m) => t m (stT ())
- captureM :: MonadBaseControl b m stM => m (stM ())
- liftBaseOp :: MonadBaseControl b m stM => ((a -> b (stM c)) -> b (stM d)) -> (a -> m c) -> m d
- liftBaseOp_ :: MonadBaseControl b m stM => (b (stM a) -> b (stM c)) -> m a -> m c
- liftBaseDiscard :: MonadBaseControl b m stM => (b () -> b a) -> m () -> m a
- liftBaseOpDiscard :: MonadBaseControl b m stM => ((a -> b ()) -> b c) -> (a -> m ()) -> m c
- liftThrough :: (MonadTransControl t stT, Monad (t m), Monad m) => (m (stT a) -> m (stT b)) -> t m a -> t m b
MonadTransControl
class MonadTrans t => MonadTransControl t stT | t -> stT where Source #
Methods
liftWith :: Monad m => (Run t stT -> m a) -> t m a Source #
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.
restoreT :: Monad m => m (stT a) -> t m a Source #
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 ListT [] Source # | |
| MonadTransControl MaybeT Maybe Source # | |
| MonadTransControl (IdentityT :: (Type -> Type) -> Type -> Type) Identity Source # | |
| MonadTransControl (ReaderT r) Identity Source # | |
| Error e => MonadTransControl (ErrorT e) (Either e) Source # | |
| MonadTransControl (ExceptT e) (Either e) Source # | |
| MonadTransControl (StateT s) ((,) s) Source # | |
| MonadTransControl (StateT s) ((,) s) Source # | |
| Monoid w => MonadTransControl (WriterT w) ((,) w) Source # | |
| Monoid w => MonadTransControl (WriterT w) ((,) w) Source # | |
| Monoid w => MonadTransControl (RWST r w s) ((,,) w s) Source # | |
| Monoid w => MonadTransControl (RWST r w s) ((,,) w s) Source # | |
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 stT = forall n b. Monad n => t n b -> n (stT b) Source #
A function like Run that runs a monad transformer t which wraps the
monad transformer t'. This is used in defaultLiftWith.
Arguments
| :: (Monad m, MonadTransControl n stT) | |
| => (forall b. n m b -> t m b) | Monad constructor |
| -> (forall o b. t o b -> n o b) | Monad deconstructor |
| -> (RunDefault t stT -> m a) | |
| -> t m a |
Default definition for the liftWith method.
Arguments
| :: (Monad m, MonadTransControl n stT) | |
| => (n m a -> t m a) | Monad constructor |
| -> m (stT a) | |
| -> t m a |
Default definition for the restoreT method.
MonadBaseControl
class MonadBase b m => MonadBaseControl b m stM | m -> b stM where Source #
Methods
liftBaseWith :: (RunInBase m b stM -> b a) -> m a Source #
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.
restoreM :: stM a -> m a Source #
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
type RunInBase m b stM = forall a. m a -> b (stM a) Source #
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 RunInBaseDefault (t :: (* -> *) -> * -> *) (m :: * -> *) (b :: * -> *) (stM :: * -> *) (stT :: * -> *) = forall a. t m a -> b (Compose stM stT a) Source #
A function like RunInBase that runs a monad transformer t in its base
monad b. It is used in defaultLiftBaseWith.
defaultLiftBaseWith :: (MonadTransControl t stT, MonadBaseControl b m stM) => (RunInBaseDefault t m b stM stT -> b a) -> t m a Source #
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 :: (MonadTransControl t stT, MonadBaseControl b m stM) => Compose stM stT a -> t m a Source #
Utility functions
control :: MonadBaseControl b m stM => (RunInBase m b stM -> b (stM a)) -> m a Source #
An often used composition: control f = liftBaseWith f >>= restoreM
controlT :: (MonadTransControl t stT, Monad (t m), Monad m) => (Run t stT -> m (stT a)) -> t m a Source #
embed :: MonadBaseControl b m stM => (a -> m c) -> m (a -> b (stM c)) Source #
Embed a transformer function as an function in the base monad returning a mutated transformer state.
embed_ :: MonadBaseControl b m stM => (a -> m ()) -> m (a -> b ()) Source #
Performs the same function as embed, but discards transformer state
from the embedded function.
captureT :: (MonadTransControl t stT, Monad (t m), Monad m) => t m (stT ()) Source #
Capture the current state of a transformer
captureM :: MonadBaseControl b m stM => m (stM ()) Source #
Capture the current state above the base monad
liftBaseOp :: MonadBaseControl b m stM => ((a -> b (stM c)) -> b (stM d)) -> (a -> m c) -> m d Source #
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 ::MonadBaseControlIOm => (Ptr a -> m c) -> m c
liftBaseOp_ :: MonadBaseControl b m stM => (b (stM a) -> b (stM c)) -> m a -> m c Source #
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_ ::MonadBaseControlIOm => m a -> m a
liftBaseDiscard :: MonadBaseControl b m stM => (b () -> b a) -> m () -> m a Source #
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 ::MonadBaseControlIOm => m () -> m ThreadId
liftBaseOpDiscard :: MonadBaseControl b m stM => ((a -> b ()) -> b c) -> (a -> m ()) -> m c Source #
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) ::MonadBaseControlIOm => m () -> m ()
liftThrough :: (MonadTransControl t stT, Monad (t m), Monad m) => (m (stT a) -> m (stT b)) -> t m a -> t m b Source #
Transform an action in t m using a transformer that operates on the underlying monad m