Wrap functions such as catch around different monads.
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.