| Portability | Requires RankNTypes |
|---|---|
| Stability | experimental |
| Maintainer | Bas van Dijk <[email protected]> |
Control.Monad.Trans.Control
Contents
Description
This module defines the class MonadTransControl of monad transformers
through which control operations can be lifted. Instances are
included for all the standard monad transformers from the
transformers library except ContT.
idLiftControl and liftLiftControlBase are provided to assist creation of
MonadControlIO-like classes (see Control.Monad.IO.Control) based on core
monads other than IO.
- class MonadTrans t => MonadTransControl t where
- liftControl :: Monad m => (Run t -> m α) -> t m α
- type Run t = forall n o β. (Monad n, Monad o, Monad (t o)) => t n β -> n (t o β)
- control :: (Monad m, Monad (t m), MonadTransControl t) => (Run t -> m (t m α)) -> t m α
- idLiftControl :: Monad m => (RunInBase m m -> m α) -> m α
- type RunInBase m base = forall β. m β -> base (m β)
- liftLiftControlBase :: (MonadTransControl t, Monad (t m), Monad m, Monad base) => ((RunInBase m base -> base α) -> m α) -> (RunInBase (t m) base -> base α) -> t m α
MonadTransControl
class MonadTrans t => MonadTransControl t whereSource
MonadTransControl is the class of monad transformers supporting an
extra operation liftControl, enabling control operations (functions that
use monadic actions as input instead of just output) to be lifted
through the transformer.
Methods
liftControl :: Monad m => (Run t -> m α) -> t m αSource
liftControl is used to peel off the outer layer of a transformed
monadic action, allowing an transformed action t m a to be
treated as a base action m a.
More precisely, liftControl captures the monadic state of t at the
point where it is bound (in t m), yielding a function of type:
Run t = forall n o b. (Monad n, Monad o) => t n b -> n (t o b)This function runs a transformed monadic action t n b
in the inner monad n using the captured state, and leaves the
result t o b in the monad n after all side effects in n
have occurred.
This can be used to lift control operations with types such as
M a -> M a into the transformed monad t M:
instance Monad M foo :: M a -> M a foo' :: (MonadTransControlt,Monad(t M)) => t M a -> t M a foo' a =control$ run -> -- run :: t M a -> M (t M a) foo $ run a -- uses foo :: M (t M a) -> M (t M a)
Instances should satisfy similar laws as the MonadTrans laws:
liftControl . const . return = return
liftControl (const (m >>= f)) = liftControl (const m) >>= liftControl . const . f
Additionally instances should satisfy:
control $ \run -> run t = tInstances
| MonadTransControl MaybeT | |
| MonadTransControl ListT | |
| MonadTransControl IdentityT | |
| Monoid w => MonadTransControl (WriterT w) | |
| Monoid w => MonadTransControl (WriterT w) | |
| MonadTransControl (StateT s) | |
| MonadTransControl (StateT s) | |
| MonadTransControl (ReaderT r) | |
| Error e => MonadTransControl (ErrorT e) | |
| Monoid w => MonadTransControl (RWST r w s) | |
| Monoid w => MonadTransControl (RWST r w s) |
control :: (Monad m, Monad (t m), MonadTransControl t) => (Run t -> m (t m α)) -> t m αSource
An often used composition: control =
join . liftControl
Lifting
idLiftControl :: Monad m => (RunInBase m m -> m α) -> m αSource
idLiftControl acts as the "identity" liftControl operation from a monad
m to itself.
idLiftControl f = f $ liftM return
It serves as the base case for a class like MonadControlIO, which
allows control operations in some base monad (here IO) to be
lifted through arbitrary stacks of zero or more monad transformers
in one call. For example, Control.Monad.IO.Control defines:
class MonadIO m => MonadControlIO m where
liftControlIO :: (RunInBase m IO -> IO b) -> m b
instance MonadControlIO IO where
liftControlIO = idLiftControl
Arguments
| :: (MonadTransControl t, Monad (t m), Monad m, Monad base) | |
| => ((RunInBase m base -> base α) -> m α) |
|
| -> (RunInBase (t m) base -> base α) -> t m α |
liftLiftControlBase is used to compose two liftControl operations:
the outer provided by a MonadTransControl instance,
and the inner provided as the argument.
It satisfies .
liftLiftControlBase idLiftControl = liftControl
It serves as the induction step of a MonadControlIO-like class. For
example, Control.Monad.IO.Control defines:
instance MonadControlIO m => MonadControlIO (StateT s m) where
liftControlIO = liftLiftControlBase liftControlIO
using the MonadTransControl instance of .
StateT s
The following shows the recursive structure of liftControlIO applied to a
stack of three monad transformers with IO as the base monad: t1 (t2 (t3 IO)) a:
liftControlIO =liftLiftControlBase$liftLiftControlBase$liftLiftControlBase$idLiftControl= \f ->liftControl$ \run1 -> -- Capture state of t1, run1 ::Runt1liftControl$ \run2 -> -- Capture state of t2, run2 ::Runt2liftControl$ \run3 -> -- Capture state of t3, run3 ::Runt3 let run ::RunInBase(t1 (t2 (t3 IO))) IO run = -- Restore stateliftM(join.lift) -- :: IO ( t2 (t3 IO) (t1 (t2 (t3 IO)) a)) -> IO ( t1 (t2 (t3 IO)) a) .liftM(join.lift) -- :: IO ( t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a))) -> IO ( t2 (t3 IO) (t1 (t2 (t3 IO)) a)) -- Identity conversion .liftM(join.lift) -- :: IO (IO (t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)))) -> IO ( t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a))) .liftMreturn-- :: IO ( t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a))) -> IO (IO (t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)))) -- Run (computation to run:) (inner monad:) (restore computation:) . run3 -- :: t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)) -> IO (t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a))) . run2 -- :: t2 (t3 IO) (t1 (t2 (t3 IO)) a) -> t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)) . run1 -- :: t1 (t2 (t3 IO)) a -> t2 (t3 IO) (t1 (t2 (t3 IO)) a) in f run