The monad-wrap package

This package allows you to invoke a function on one monadic
type passing it an argument of a different monadic type. The
canonical example is using a function such as finally or
bracket to ensure cleanup is run regardless of any
exceptions thrown by a computation such as x :: ReaderT
MyConfig IO b. If x uses the ReaderT function ask,
it cannot be re-written to run in the IO monad, and hence
cannot be executed with a construction like lift (x
`finally` cleanup). Instead, you must use the wrap
method, provided by module Control.Monad.Wrap in this
package.

This package contains several other modules:
Control.Monad.WrapIO wraps an IO action through multiple
monad transformers. Control.Monad.WrapBase generalizes the
concept to other base monads besides IO.
Control.Monad.MultiWrap implements mwrap, a method that
behaves like wrap but allows wrapping through multiple
nested layers of monad transformer. The module
Control.Monad.MultiLift provides mlift, a version of
lift that similarly lifts through multiple nested monad
transformers.

Since this library was first released, an alternate approach
was introduced by the monad-control package.
monad-control is now the standard. However, this package,
monad-wrap, stands as an example of accomplishing similar
goals with fewer language extensions and less complexity. In
particular, monad-wrap does not use RankNTypes or
TypeFamilies, both required by monad-control. Moreover,
monad-wrap is much smaller--no MonadWrap method requires
more than one line of code. Both monad-wrap and
monad-control require UndecidableInstances, but
Control.Monad.Wrap itself does not require that extension,
only the other modules.