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.gitCaughtMonadIO 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 IORefs.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.