[EMAIL PROTECTED] 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

I still don't see how this helps with the StateT transformer for example, because the state would be lost which isn't much use. For example, here is my attempt to implement a version of bracket_ which would work with an arbitrary StrictMonadIO:

class MonadIO m => StrictMonadIO m where
 getUnliftIO :: m (m a -> IO a)

instance StrictMonadIO IO where
 getUnliftIO = return id

instance StrictMonadIO m => StrictMonadIO (StateT s m) where
 getUnliftIO = StateT $ \s ->
                  do
                    unliftIO <- getUnliftIO
                    return (\(StateT s_mas) ->
                              do
(a, _) <- unliftIO (s_mas s) -- NEW STATE LOST
                                 return a
                           , s) -- OLD STATE IS RETURNED

bracket_ :: StrictMonadIO m => m a -> m b -> m c -> m c
bracket_ a b c = do
                  unliftIOa <- getUnliftIO
                  unliftIOb <- getUnliftIO
                  unliftIOc <- getUnliftIO
liftIO $ bracket_ (unliftIOa a) (unliftIOb b) (unliftIOc c)

There are some points that are problematic:

1) Any changes made to the state by unlifted actions are discarded
2) The implementation of bracket_ seems unnecessarily messy because of the strange limitation that higher rank polymorphism is not allowed ie the following definition gives a compiler error:

  getUnliftIO :: m (forall a. m a -> IO a)  -- what's wrong with this?

So the essential question is: does there exist any way to implement a bracket_ that will work properly with a state monad?

I'm also wondering: exactly why is it impossible to implement the Exception functions for an arbitrary MonadIO? Surely the higher order functions could just be implemented using some very low level primitives like:

   push_block_async :: IO ()
   pop_block_async :: IO ()
   push_unblock_async :: IO ()
   pop_unblock_async :: IO ()

   block :: MonadIO m -> m a -> m a
   block x = do
                       liftIO push_block_async
                       a <- x
                       liftIO pop_block_async
                       return a

    bracket_ a b c = block $ do
                                    a
                                    unblock c
                                    b

Thanks, Brian.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to