Lift control operations like exception catching through monad transformers
This package defines MonadPeelIO
, a subset
of MonadIO
into which generic control operations such
as catch
can be lifted from IO
. Instances
are based on monad transformers in MonadTransPeel
, which
includes all standard monad transformers in
the transformers
library except ContT
. For
convenience, it provides a wrapped version of Control.Exception with
types generalized from IO
to all monads
in MonadPeelIO
.
git clone git://andersk.mit.edu/haskell/monad-peel.git
CaughtMonadIO
with a gcatch
method generalizing catch
. Ashley Yakeley suggests class StrictMonadIO
containing getUnliftIO
, which is powerful enough to construct gcatch
, but does not present an implementation.StrictMonadIO
cannot be correctly implemented for stateful monad transformers, and proposes class MonadException
containing catch
, block
, unblock
, and setUncaughtExceptionHandler
.class InterleavableIO
which threads monadic state through IO
using IORef
s.class MonadCatchIO
with catch
, block
, and unblock
(similar to Hulley’s MonadException
).class MonadWrap
with wrap
and resultF
, using MPTC+FDs; it seems to allow a limited kind of monadic catching where the handler runs in IO
.class MonadMorphIO
, which uses rank-2 types and is powerful enough to construct a fully-general catch
. I implement it for all monads in MTL, though David Menendez points out that instance for ContT
is wrong. Wren Ng Thornton attempts to exhibit an isomorphism with a simpler class MonadJoinIO
that is Haskell 98, but it doesn’t quite work for ReaderT
.finally
implementation in MonadCatchIO
is broken in monads with short-circuiting control flow, showing that a general finally
needs to be derived from the finally
in IO
and not just from a general catch
.class MonadInvertIO
with invertIO
and revertIO
, using type families; this is powerful enough to generalize everything in Control.Exception including catch
and finally
. I reply with a way to combine this idea with MonadMorphIO
to get a solution that uses only rank-2 types, but is not quite powerful enough to generalize bracket
. Thinking through this problem and combining several of the ideas above eventually led to MonadPeelIO
.