
oleg@pobox.com wrote:
Robert Dockins wrote:
One additional (very unfortunate) point is that higher-order IO monad combinators will not work on your monad, eg, the ones in Control.Exception.
Although that is true in general, for many useful and interesting cases (including ReaderT, the state transformer, and the newtype wrapping of IO) one _can_ use catch, bracket etc. constructs in MonadIO. Please see this message and the follow-up discussion:
http://www.haskell.org/pipermail/haskell/2006-February/017547.html
If it is true that it is absolutely impossible to implement Control.Exception for any MonadIO (it would be useful to know why cf the old saying "there is no such word as can't"), the other option seems to be to re-organise Control.Exception to make use of different monads that could support the various subsets of operations, as you've begun in the thread above by defining CaughtMonadIO. Perhaps something like: class MonadIO m => MonadIOE m where catch :: m a-> (Exception -> m a) -> m a throw catchDyn throwDyn -- etc instance MonadIOE m => StateT s m where ... instance MonadIOE m => ReaderT r m where ... blockIO :: IO a -> IO a class MonadIO m => MonadIOB m where getUnliftIO :: m (m a -> IO a) block :: m a -> m a block x = do unliftIO <- getUnliftIO liftIO (blockIO (unliftIO x)) unblock :: m a -> m a bracket_ :: m a -> m b -> m c -> m c -- etc instance MonadIOB m => ReaderT r m where ... and then we could just get rid of all the other exception handling functions scattered all over the code base eg Prelude.catch etc. StateT s can be an instance of MonadIOE but not of MonadIOB because although it is sometimes fine to discard state changes when an exception arises, it is not ok to discard the state changes inside a block (or unblock, bracket_ etc). Does the above look like a good way of organising things? (I don't know whether MonadIOB would require MonadIOE or not since I haven't tried to implement all these functions yet - if it did I would use the name MonadIOEB instead) I'm about to make an attempt along these lines myself since I can't go further in my own work without a proper exception api that doesn't drag everything down to concrete IO (unless someone else has already done this?) Also, would it be worth modifying http://hackage.haskell.org/trac/haskell-prime/ticket/110 to include something like this (someone more knowledgeable than me would have to do it)? Regards, Brian.