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

Stabilityexperimental
MaintainerBas van Dijk <v.dijk.bas@gmail.com>
Safe HaskellSafe-Infered

Control.Monad.Trans.Control

Contents

Description

(TODO: It would be nicer if the associated data types StT and StM were associated type synonyms instead. This would simplify a lot of code and could make some definitions more efficient because there'll be no need to wrap the monadic state in a data type. Unfortunately GHC has a bug which prevents this: http://hackage.haskell.org/trac/ghc/ticket/5595. I will switch to associated type synonyms when that bug is fixed.)

Synopsis

Documentation

class MonadTrans t => MonadTransControl t whereSource

Associated Types

data StT t :: * -> *Source

Monadic state of t.

Methods

liftWith :: Monad m => (Run t -> m α) -> t m α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 . 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 α) -> t m α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

type Run t = forall n β. Monad n => t n β -> n (StT t β)Source

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.

class MonadBase b m => MonadBaseControl b m | m -> b whereSource

Associated Types

data StM m :: * -> *Source

Monadic state of m.

Methods

liftBaseWith :: (RunInBase m b -> b α) -> m α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 . 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 α -> m α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

type RunInBase m b = forall α. m α -> b (StM m α)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 for MonadBaseControl

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
     newtype StM (T m) a = StMT {unStMT :: ComposeSt T m a}
     liftBaseWith = defaultLiftBaseWith StMT
     restoreM     = defaultRestoreM   unStMT

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

 instance MonadBaseControl B B where
     newtype StM B a = StMB {unStMB :: a}
     liftBaseWith f  = f $ liftM  StMB
     restoreM        = return . unStMB

type ComposeSt t m α = StM m (StT t α)Source

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

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

defaultLiftBaseWithSource

Arguments

:: (MonadTransControl t, MonadBaseControl b m) 
=> (forall β. ComposeSt t m β -> StM (t m) β)

StM constructor

-> (RunInBase (t m) b -> b α) -> t m α 

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 stM = \f -> liftWith $ \run ->
                                   liftBaseWith $ \runInBase ->
                                     f $ liftM stM . runInBase . run

defaultRestoreMSource

Arguments

:: (MonadTransControl t, MonadBaseControl b m) 
=> (StM (t m) α -> ComposeSt t m α)

StM deconstructor

-> StM (t m) α -> t m α 

Default definition for the restoreM method.

Note that: defaultRestoreM unStM = restoreT . restoreM . unStM

Utility functions

control :: MonadBaseControl b m => (RunInBase m b -> b (StM m α)) -> m αSource

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

liftBaseOp :: MonadBaseControl b m => ((α -> b (StM m β)) -> b (StM m γ)) -> (α -> m β) -> m γ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 :: MonadBaseControl IO m => (Ptr a -> m c) -> m c

liftBaseOp_ :: MonadBaseControl b m => (b (StM m α) -> b (StM m β)) -> m α -> m β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_ :: MonadBaseControl IO m => m a -> m a

liftBaseDiscard :: MonadBaseControl b m => (b () -> b α) -> m () -> m α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 :: MonadBaseControl IO m => m () -> m ThreadId