
On Sun, 11 Apr 2010, Bas van Dijk wrote:
Of course when this change is made the MonadCatchIO class has to be adapted to something like:
class MonadIO m => MonadCatchIO m where catch :: Exception e => m a -> (e -> m a) -> m a mask :: ((m b -> m b) -> m a) -> m a
The striking similarity between instances of MonadCatchIO suggests to me that something deeper is going on. Is there a cleaner abstraction that captures this idea? instance ( MonadCatchIO m) => MonadCatchIO (ReaderT r m) where m `catch` f = ReaderT $ \r -> runReaderT m r `catch` \e -> runReaderT (f e) r mask io = ReaderT $ \r -> mask $ \restore -> runReaderT (io $ mapReaderT restore) r instance ( MonadCatchIO m) => MonadCatchIO (StateT s m) where m `catch` f = StateT $ \s -> runStateT m s `catch` \e -> runStateT (f e) s mask io = StateT $ \s -> mask $ \restore -> runStateT (io $ mapStateT restore) s instance (Error e, MonadCatchIO m) => MonadCatchIO (ErrorT e m) where m `catch` f = ErrorT $ runErrorT m `catch` \e -> runErrorT (f e) mask io = ErrorT $ mask $ \restore -> runErrorT (io $ mapErrorT restore) instance (Monoid r, MonadCatchIO m) => MonadCatchIO (WriterT r m) where m `catch` f = WriterT $ runWriterT m `catch` \e -> runWriterT (f e) mask io = WriterT $ mask $ \restore -> runWriterT (io $ mapWriterT restore) instance (Monoid w, MonadCatchIO m) => MonadCatchIO (RWST r w s m) where m `catch` f = RWST $ \r s -> runRWST m r s `catch` \e -> runRWST (f e) r s mask io = RWST $ \r s -> mask $ \restore -> runRWST (io $ mapRWST restore) r s instance ( MonadCatchIO m) => MonadCatchIO (ListT m) where m `catch` f = ListT $ runListT m `catch` \e -> runListT (f e) mask io = ListT $ mask $ \restore -> runListT (io $ mapListT restore) instance ( MonadCatchIO m) => MonadCatchIO (ContT r m) where m `catch` f = ContT $ \c -> runContT m c `catch` \e -> runContT (f e) c mask io = ContT $ \c -> mask $ \restore -> runContT (io $ mapContT restore) c (By the way, these last two don’t seem to be in the current MonadCatchIO packages. Any reason why not?) Anders