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

Copyright Bas van Dijk Anders Kaseorg BSD-style Bas van Dijk experimental Safe Haskell98

Description

Synopsis

class MonadTrans t => MonadTransControl t where Source #

Minimal complete definition

Associated Types

type StT t a :: * Source #

Monadic state of t.

For clarity, because haddock does not display associated types, below are the elaborated StT definitions provided by this library:

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 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 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

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

type Run t = forall n b. Monad n => t n b -> n (StT t b) 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.

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)


## 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 #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeFamilies #-}

newtype CounterT m a = CounterT {unCounterT :: StateT Int m a}

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) 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) => (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.

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.

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 }

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 n n' = forall m b. (Monad m, Monad (n' m)) => t m b -> m (StT n' (StT n b)) Source #

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

Arguments

 :: (Monad m, Monad (n' m), MonadTransControl n, MonadTransControl n') => (forall b. n (n' m) b -> t m b) Monad constructor -> (forall o 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.

Arguments

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

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

Minimal complete definition

Associated Types

type StM m a :: * Source #

Monadic state of m.

For all non-transformer 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


All transformer monads' StM depends on both the monadic state of the transformer (given by its StT from MonadTransControl), as well as its inner monad's monadic state, given by its StM from MonadBaseControl:

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


Methods

liftBaseWith :: (RunInBase m b -> 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 . 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 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 = forall a. m a -> b (StM m 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.

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))


## 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) 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.

type RunInBaseDefault t m b = forall a. t m a -> b (ComposeSt t m 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, MonadBaseControl b m) => (RunInBaseDefault t m b -> b a) -> t m a Source #

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 Source #

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 Source #

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

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

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 ()) Source #

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 ()) Source #

Capture the current state of a transformer

captureM :: MonadBaseControl b m => m (StM m ()) Source #

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

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

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

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