Portability | portable |
---|---|

Stability | experimental |

Maintainer | Anders Kaseorg <andersk@mit.edu> |

Safe Haskell | Safe-Inferred |

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.

- class MonadTrans t => MonadTransPeel t where
- idPeel :: (Monad m, Monad n, Monad o) => n (m a -> m (o a))
- 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))
- 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
- 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

# Documentation

class MonadTrans t => MonadTransPeel t whereSource

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

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`

.

MonadTransPeel MaybeT | |

MonadTransPeel ListT | |

MonadTransPeel IdentityT | |

(MonadTrans (WriterT w), Monoid w) => MonadTransPeel (WriterT w) | |

(MonadTrans (WriterT w), Monoid w) => MonadTransPeel (WriterT w) | |

MonadTrans (StateT s) => MonadTransPeel (StateT s) | |

MonadTrans (StateT s) => MonadTransPeel (StateT s) | |

MonadTrans (ReaderT r) => MonadTransPeel (ReaderT r) | |

(MonadTrans (ErrorT e), Error e) => MonadTransPeel (ErrorT e) | |

(MonadTrans (RWST r w s), Monoid w) => MonadTransPeel (RWST r w s) | |

(MonadTrans (RWST r w s), Monoid w) => MonadTransPeel (RWST r w s) |

idPeel :: (Monad m, Monad n, Monad o) => n (m a -> m (o a))Source

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