On 11/14/2011 06:55 AM, Bas van Dijk wrote:
Hi Mikhail,

your type class:

class MonadAbort e μ ⇒ MonadRecover e μ | μ → e where
   recover ∷ μ α → (e → μ α) → μ α

looks a lot like the MonadCatchIO type class from MonadCatchIO-transformers:

class MonadIO m =>  MonadCatchIO m where
   catch   :: E.Exception e =>  m a ->  (e ->  m a) ->  m a

I haven't looked at your code in detail but are you sure your
continuation based AIO monad doesn't suffer from the same unexpected
behavior as the ContT monad transformer with regard to catching and
handling exceptions?
Yes, I'm sure. The reason why it works is because finally/bracket/etc are not implemented on top of 'recover' (i.e. they don't assume that throwing an exception is the only reason control can escape). The following class takes care of it:

class (Applicative μ, Monad μ) ⇒ MonadFinally μ where
  finally' ∷ μ α → (Maybe α → μ β) → μ (α, β)
  finally ∷ μ α → μ β → μ α
  finally m = fmap fst . finally' m . const

Finalizers have type 'Maybe α → μ β' so we can

(a) Thread transformer side effects properly:

instance MonadFinally μ ⇒ MonadFinally (L.StateT s μ) where
  finally' m f = L.StateT $ \s → do
    ~(~(mr, _), ~(fr, s'')) ← finally' (L.runStateT m s) $ \mbr → do
      let ~(a, s') = case mbr of
             Just ~(x, t) → (Just x, t)
             Nothing → (Nothing, s)
      L.runStateT (f a) s'
    return ((mr, fr), s'')

(b) Detect that control escaped computation before producing a result (finalizer will be called with 'Nothing' in that case).

instance (MonadFinally μ, Error e) ⇒ MonadFinally (ErrorT e μ) where
  finally' m f = ErrorT $ do
    ~(mr, fr) ← finally' (runErrorT m) $ \mbr →
      runErrorT $ f $ case mbr of
        Just (Right a) → Just a
        _ → Nothing
    return $ (,) <$> mr <*> fr

That of course does not mean that I can use 'finally' and friends with ContT, but I can use them with monads which are carefully /implemented/ on top of ContT but do not expose it's full power to the users.

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to