Description

This module defines the class MonadTransPeel 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.

idPeel and liftPeel are provided to assist creation of MonadPeelIO-like classes (see Control.Monad.IO.Peel) based on core monads other than IO.

liftOp and liftOp_ enable convenient lifting of two common special cases of control operation types.

Synopsis

# Documentation

MonadTransPeel is the class of monad transformers supporting an extra operation peel, enabling control operations (functions that use monadic actions as input instead of just output) to be lifted through the transformer.

Minimal complete definition

peel

Methods

peel :: (Monad m, Monad n, Monad o) => t n (t m a -> m (t o a)) Source #

peel 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 b.

More precisely, peel captures the monadic state of t at the point where it is bound (in t n), yielding a function t m a -> m (t o a); this function runs a transformed monadic action t m a in the base monad m using the captured state, and leaves the result t o a in the monad m after all side effects in m have occurred.

This can be used together with lift 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' :: (MonadTransPeel t, Monad (t M)) => t M a -> t M a
foo' a = do
k <- peel  -- k :: t M a -> M (t M a)
join $lift$ foo (k a)  -- uses foo :: M (t M a) -> M (t M a)


peel is typically used with m == n == o, but is required to be polymorphic for greater type safety: for example, this type ensures that the result of running the action in m has no remaining side effects in m.

Instances

idPeel acts as the "identity" peel operation from a monad m to itself.
   idPeel = return $liftM return  It serves as the base case for a class like MonadPeelIO, 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.Peel defines  class MonadIO m => MonadPeelIO m where peelIO :: m (m a -> IO (m a)) instance MonadPeelIO IO where peelIO = idPeel  liftPeel :: (MonadTransPeel t, Monad m, Monad m', Monad n', Monad (t n'), Monad o', Monad (t o')) => n' (m' (t o' a) -> m (o' (t o' a))) -> t n' (t m' a -> m (t o' a)) Source # liftPeel is used to compose two peel operations: the outer provided by a MonadTransPeel instance, and the inner provided as the argument. It satisfies liftPeel idPeel == peel. It serves as the induction step of a MonadPeelIO-like class. For example, Control.Monad.IO.Peel defines  instance MonadPeelIO m => MonadPeelIO (StateT s m) where peelIO = liftPeel peelIO  using the MonadTransPeel instance of StateT s. liftOp :: (MonadTransPeel t, Monad m, Monad n, Monad o, Monad (t n)) => ((a -> m (t o b)) -> n (t n c)) -> (a -> t m b) -> t n c Source # liftOp is a particular application of peel that allows lifting control operations of type (a -> m b) -> m b to MonadTransPeel t => (a -> t m b) -> t m b.  liftOp f g = do k <- peel join$ lift $f (k . g)  liftOp_ :: (MonadTransPeel t, Monad m, Monad n, Monad o, Monad (t n)) => (m (t o a) -> n (t n b)) -> t m a -> t n b Source # liftOp_ is a particular application of peel that allows lifting control operations of type m a -> m a to MonadTransPeel m => t m a -> t m a. It can be thought of as a generalization of mapReaderT, mapStateT, etc.  liftOp_ f m = do k <- peel join$ lift \$ f (k m)