[Haskell-cafe] Re: Control.Exceptions and MonadIO
Brian Hulley
brianh at metamilk.com
Mon Apr 24 10:25:55 EDT 2006
Brian Hulley wrote:
> I've started work on a module to replace Control.Exception by
> wrapping all the original Control.Exception functions in more general
> monadic functions and using two type classes as follows:
>
> class MonadIO m => MonadException m where
> catch :: m a -> (Exception -> m a) -> m a
> catchDyn :: Typeable exception => m a -> (exception -> m a) -> m a
> catchJust :: (Exception -> Maybe b) -> m a -> (b -> m a) -> m a
> try :: m a -> m (Either Exception a)
> tryJust :: (Exception -> Maybe b) -> m a -> m (Either b a)
>
> and
>
> class MonadIO m => MonadIOU m where
> getUnliftIO :: m (m a -> IO a)
>
> All the other functions can be implemented just using MonadIO or
> MonadIOU or MonadException in place of IO (depending on the function
> eg bracket needs MonadIOU) - just in case anyone is interested.
After more thought, it seems that it *should* be possible to implement block
and unblock for StateT monads under certain conditions, using a different
unlift function to return IO (a,s) instead of just IO a. Therefore I've
changed things around, and also by looking at the source code for the
current Control.Exception module, arrived at the following revised design
(I've implemented all the other functions in terms of the classes below)
class MonadIO m => MonadException m where
catch :: m a -> (Exception -> m a) -> m a
catchDyn :: Typeable exception => m a -> (exception -> m a) -> m a
block, unblock :: MonadException m => m a -> m a
class MonadIO m => MonadIOU m where
getUnliftIO :: m (m a -> IO a)
However I then want to say that any instance of MonadIOU is also an instance
of MonadException. I tried:
instance MonadIOU m => MonadException m where
catch action e_m = do
unliftIOa <- getUnliftIO
unliftIOb <- getUnliftIO
liftIO $ C.catch (unliftIOa action) (\e -> unliftIOb(e_m e))
-- etc
but this only compiles with -fallow-undecidable-instances. I'm puzzled at
why there is a problem with such a simple instance declaration, and also
don't know if this means my design is fatally flawed.
The highlight of the above design is that all that's needed for many monads
such as MonadIOU m => ReaderT r m is a definition of the one unlifting
function, but it also allows instances of MonadException to be declared
where the monad (eg a StateT s m) doesn't support this particular operation.
Any ideas?
Thanks, Brian.
More information about the Haskell-Cafe
mailing list