layers-0.1: Modular type class machinery for monad transformer stacks.

Safe HaskellNone

Control.Monad.Layer

Contents

Description

This module is the core of the layers package. It exports:

  1. The type classes MonadLayer, MonadLayerFunctor and MonadLayerControl and instances of these classes for the transformers in the transformers package.
  2. The type classes MonadTrans, MonadTransFunctor and MonadTransControl and instances of these classes for the transformers in the transformers package.
  3. The type classes MonadLift, MonadLiftFunctor and MonadLiftControl.
  4. Two sets of helper functions inspired by similarly named functions in the monad-control package: one for instances of MonadLayerControl and the other for instances of MonadLiftControl. These operations are: controlLayer, layerOp, layerOp_ and layerDiscard and control, liftOp, liftOp_ and liftDiscard respectively.

Synopsis

The MonadLayer family

class (Monad m, Monad (Inner m)) => MonadLayer m whereSource

A monad m can be an instance of MonadLayer if it is built ("layered") on top of some inner monad (Inner m) and can provide the operations layer and layerInvmap.

Monad layers are a generalisation of monad transformers, with the difference being that monad layers are not necessarily parametric in their inner monad. For more details, read the the in-depth documentation provided in Documentation.Layers.Overview.

Associated Types

type Inner m :: * -> *Source

The inner monad on top of which m is built.

Methods

layer :: Inner m a -> m aSource

layer takes a computation from the inner monad Inner m and lifts it into the "outer" monad m.

The following laws hold for valid instances of MonadLayer:

Identity
layer . return = return
Composition
layer m >>= layer . f = layer (m >>= f)

These laws are equivalent to the monad transformer laws of the MonadTrans class from the transformers, where layer is analgous to the lift operation from MonadTrans.

layerInvmapSource

Arguments

:: (forall b. Inner m b -> Inner m b)

f

-> (forall b. Inner m b -> Inner m b)

g

-> m a 
-> m a 

layerInvmap represents an invariant (endo)functor in the category of monads. It takes a transformation f of the inner monad and its inverse g (such that g . f = id) and returns transformation of m analogous to f. (i.e., layerInvmap lifts an automorphism of Inner m to an endomorphism of m).

The following laws hold for valid instances of MonadLayer:

Identity
layerInvmap id id = id
Composition
layerInvmap f g . layerInvmap f' g' = layerInvmap (f . f') (g' . g)

Instances

Monad m => MonadLayer (MaybeT m) 
Monad m => MonadLayer (ListT m) 
Monad m => MonadLayer (IdentityT m) 
(Monad m, Monoid w) => MonadLayer (WriterT w m) 
(Monad m, Monoid w) => MonadLayer (WriterT w m) 
Monad m => MonadLayer (StateT s m) 
Monad m => MonadLayer (StateT s m) 
Monad m => MonadLayer (ReaderT r m) 
(Error e, Monad m) => MonadLayer (ErrorT e m) 
Monad m => MonadLayer (ContT r m) 
(Monad m, Monoid w) => MonadLayer (RWST r w s m) 
(Monad m, Monoid w) => MonadLayer (RWST r w s m) 

class MonadLayer m => MonadLayerFunctor m whereSource

The type class MonadLayerFunctor represents is the subclass of monad layers that support the layerMap operation, which is more powerful than the layerInvmap operation of the MonadLayer type class.

Methods

layerMap :: (forall b. Inner m b -> Inner m b) -> m a -> m aSource

layerMap represents an (endo)functor in the category of monads. It takes a transformation f of the inner monad returns a transformation of m analogous to f. (i.e., layerMap lifts an endomorphism of Inner m to a endomorphism of m).

The following laws hold for valid instances of MonadLayerFunctor:

Identity
layerMap id = id
Composition
layerMap f . layerMap g = layerMap (f . g)

class MonadLayerFunctor m => MonadLayerControl m whereSource

MonadLayerControl represents the class of monad layers through which it is possible to lift control operations. See Documentation.Layers.Overview for a more complete discussion.

Associated Types

data LayerState m :: * -> *Source

The portion of the monadic state of m that is independent of Inner m.

Methods

zero :: LayerState m a -> BoolSource

zero inspects a LayerState value and determines whether or not it is a "zero" value in the monad m (i.e., if m had short-circuited when the LayerState was captured). (This is used to implement the universal pass-through instance of MonadTry.)

restore :: LayerState m a -> m aSource

Construct a m computation from the monadic state of m that is returned from a run function given by layerControl.

Instances should satisfy the following law:

Preservation
layerControl (\run -> run t) >>= restore = t

layerControl :: ((forall b. m b -> Inner m (LayerState m b)) -> Inner m a) -> m aSource

layerControl is a version of layer that makes it possible to lift control operations from the inner monad Inner m to the "outer" monad m. It takes a continuation, to which it passes an operation we call run, which is a kind of "inverse" of layer.

Instances should satisfy similar laws as the monad transformer laws:

Identity
layerControl . const . return = return
Composition
layerControl (const m) >>= layerControl . const . f = layerControl (const (m >>= f))

The MonadTrans family

class (MonadLayer m, m ~ Outer m (Inner m)) => MonadTrans m whereSource

Monad transformers are a subclass of monad layers which are parametric in their inner monad.

Associated Types

type Outer m :: (* -> *) -> * -> *Source

Outer m is the monad constructor from which m is built (by applying it to Inner m).

Methods

transInvmap :: (MonadTrans n, Outer n ~ Outer m) => (forall b. Inner m b -> Inner n b) -> (forall b. Inner n b -> Inner m b) -> m a -> n aSource

transInvmap represents an invariant functor in the category of monads. It takes a transformation f from the inner monad and its inverse g (such that g . f = id) and returns transformation of m analogous to f. (i.e., layerInvmap lifts an isomorphism from Inner m to a homomorphism of m).

The following laws hold for valid instances of MonadTrans:

Identity
transInvmap id id = id
Composition
transInvmap f g . transInvmap f' g' = transInvmap (f . f') (g' . g)

Note: this is more powerful than layerInvmap from the MonadLayer type class because the transformation it produces is a homomorphism rather than just an endomorphism.

Instances

Monad m => MonadTrans (MaybeT m) 
Monad m => MonadTrans (ListT m) 
Monad m => MonadTrans (IdentityT m) 
(Monad m, Monoid w) => MonadTrans (WriterT w m) 
(Monad m, Monoid w) => MonadTrans (WriterT w m) 
Monad m => MonadTrans (StateT s m) 
Monad m => MonadTrans (StateT s m) 
Monad m => MonadTrans (ReaderT r m) 
(Error e, Monad m) => MonadTrans (ErrorT e m) 
Monad m => MonadTrans (ContT r m) 
(Monad m, Monoid w) => MonadTrans (RWST r w s m) 
(Monad m, Monoid w) => MonadTrans (RWST r w s m) 

class (MonadLayerFunctor m, MonadTrans m) => MonadTransFunctor m whereSource

The type class MonadTransFunctor represents is the subclass of monad layers that support the transMap operation, which is more powerful than the transInvmap operation of the MonadTrans type class.

Methods

transMap :: (MonadTrans n, Outer n ~ Outer m) => (forall b. Inner m b -> Inner n b) -> m a -> n aSource

transMap represents a functor in the category of monads. It takes a transformation f from the inner monad returns a transformation from m analogous to f. (i.e., transMap lifts a homomorphism from Inner m to a homomorphism from m).

The following laws hold for valid instances of MonadTransFunctor:

Identity
transMap id = id
Composition
transMap f . transMap g = transMap (f . g)

Note: this is more powerful than layerMap from the MonadLayerFunctor type class because the transformation it produces is a homomorphism rather than just an endomorphism.

class (MonadLayerControl m, MonadTransFunctor m) => MonadTransControl m whereSource

MonadTransControl is a variant of MonadLayerControl for monad transformers, i.e., monad layers polymorphic in their inner monad. This extra polymorphism allows us to specify more type safety in the run operation of transControl, but in practice there is no reason to ever use this over MonadLayerControl. See Documentation.Layers.Overview for a discussion of why this class is included despite not being strictly necessary.

Methods

transControl :: (forall n. (MonadTrans n, Outer n ~ Outer m) => (forall b. n b -> Inner n (LayerState n b)) -> Inner n a) -> m aSource

transControl is a version of layerControl whose run operation is more polymorphic in the returned monad. This provides a static guarantee that there are no remaining side effects in m in the action returned by run which is not possible to express with the types of MonadLayerControl. In practice though there should be no reason to use this over layerControl.

The MonadLift family

class (Monad i, Monad m) => MonadLift i m whereSource

MonadLift is a multi-parameter type class parameterised by two monads i and m. If the constraint MonadLift i m is satisfied, this means that m supports lifting operations from i. If m is a monad built from a monad transformer stack, then it supports lifting operations from any monad i anywhere in the stack. We call such a relationship between i and m a "monad lift". For a more details, read the in-depth documentation provided in Documentation.Layers.Overview.

Methods

lift :: i a -> m aSource

lift takes a computation from an inner monad i and lifts it into the "outer" monad m.

The following laws hold for valid instances of MonadLift:

Identity
lift . return = return
Composition
lift m >>= lift . f = lift (m >>= f)

These laws are equivalent to the monad transformer laws of the MonadTrans class from the transformers package.

liftInvmap :: (forall b. i b -> i b) -> (forall b. i b -> i b) -> m a -> m aSource

liftInvmap represents an invariant (endo)functor in the category of monads. It takes a transformation f of an inner monad i and its inverse g (such that g . f = id) and returns transformation of m analogous to f. (i.e., liftInvmap lifts an automorphism of i to an endomorphism of m).

The following laws hold for valid instances of MonadLift:

Identity
liftInvmap id id = id
Composition
liftInvmap f g . liftInvmap f' g' = liftInvmap (f . f') (g' . g)

The difference between liftInvmap and layerInvmap is that layerInvmap only lifts from the monad directly beneath the top of the stack, while liftInvmap can lift from any monad anywhere in the stack (including m itself). (layerInvmap is used to implement liftInvmap)

Instances

(MonadLayer m, MonadLift i (Inner m)) => MonadLift i m 
Monad m => MonadLift m m 

class MonadLift i m => MonadLiftFunctor i m whereSource

The type class MonadLiftFunctor represents is the subclass of monad lifts that support the liftMap operation, which is more powerful than the liftInvmap operation of the MonadLift type class.

Methods

liftMap :: (forall b. i b -> i b) -> m a -> m aSource

liftMap represents an (endo)functor in the category of monads. It takes a transformation f of an inner monad i returns a transformation of m analogous to f. (i.e., liftInvmap lifts an endomorphism of i to an endomorphism of m).

The following laws hold for valid instances of MonadLiftFunctor:

Identity
liftMap id = id
Composition
liftMap f . liftMap g = liftMap (f . g)

The difference between liftMap and layerMap is that layerMap only lifts from the monad directly beneath the top of the stack, while liftMap can lift from any monad anywhere in the stack (including m itself). (layerMap is used to implement liftMap)

class MonadLiftFunctor i m => MonadLiftControl i m whereSource

MonadLiftControl represents the class of monad lifts that support lifting control operations. See Documentation.Layers.Overview for a more complete discussion.

Methods

liftControl :: ((forall b. m b -> i (m b)) -> i a) -> m aSource

liftControl is a version of lift that makes it possible to lift control operations from an inner monad i to the "outer" monad m. It takes a continuation, to which it passes an operation we call run, which is a kind of "inverse" of lift.

Instances should satisfy the following laws:

Identity
liftControl . const . return = return
Composition
liftControl (const m) >>= liftControl . const . f = liftControl (const (m >>= f))
Preservation
join (liftControl (\run -> run t)) = t

Helper functions

MonadLayerControl

These functions are mainly used for writing universal pass-through instances for monad interfaces. If you are not doing this, you're probably looking for the analogous functions for MonadLiftControl (see below).

controlLayer :: MonadLayerControl m => ((forall b. m b -> Inner m (LayerState m b)) -> Inner m (LayerState m a)) -> m aSource

An often used composition: controlLayer f = layerControl f >>= restore

layerOp :: MonadLayerControl m => ((a -> Inner m (LayerState m b)) -> Inner m (LayerState m c)) -> (a -> m b) -> m cSource

layerOp is a particular application of layerControl that allows layering control operations of type: (a -> Inner m b) -> Inner m b to MonadLayerControl m => (a -> m b) -> m b.

For example:

layerOp . withMVar :: (MonadLayerControl m, Inner m ~ IO)
     => MVar a -> (a -> m b) -> m b

layerOp_ :: MonadLayerControl m => (Inner m (LayerState m a) -> Inner m (LayerState m b)) -> m a -> m bSource

layerOp_ is a particular application of layerControl that allows layering control operations of type: Inner m a -> Inner m b to MonadLayerControl m => m a -> m b.

For example:

layerOp_ mask_ :: (MonadLayerControl m, Inner m ~ IO) => m a -> m a

layerDiscard :: MonadLayerControl m => (Inner m () -> Inner m a) -> m () -> m aSource

layerDiscard is a particular application of layerControl that allows layering control operations of type: Inner m () -> Inner m a to MonadLayerControl 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 inner monad Inner m.

For example:

layerDiscard forkIO :: (MonadLayerControl m, Inner m ~ IO)
     => m () -> m ThreadId

MonadLiftControl

control :: MonadLiftControl i m => ((forall b. m b -> i (m b)) -> i (m a)) -> m aSource

An often used composition: control f = join . liftControl f

liftOp :: MonadLiftControl i m => ((a -> i (m b)) -> i (m c)) -> (a -> m b) -> m cSource

liftOp is a particular application of liftControl that allows lifting control operations of type: (a -> i b) -> i b to MonadLiftControl i m => (a -> m b) -> m b.

For example:

liftOp . withMVar :: MonadLiftControl IO m => MVar a -> (a -> m b) -> m b

liftOp_ :: MonadLiftControl i m => (i (m a) -> i (m b)) -> m a -> m bSource

liftOp_ is a particular application of liftControl that allows lifting control operations of type: i a -> i b to MonadLiftControl i m => m a -> m b.

For example:

liftOp_ mask_ :: MonadLiftControl IO m => m a -> m a

liftDiscard :: MonadLiftControl i m => (i () -> i a) -> m () -> m aSource

liftDiscard is a particular application of liftControl that allows lifting control operations of type: i () -> i a to MonadLiftControl i 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 inner monad i.

For example:

liftDiscard forkIO :: MonadLiftControl IO m => m () -> m ThreadId