{- | Module: Network.Monad.Exception Copyright: (c) 2009 Henning Thielemann License: BSD Stability: experimental Portability: non-portable (not tested) Functions that might be moved to explicit-exception package when they prove to be universally useful. -} module Network.Monad.Exception where import qualified Control.Monad.Exception.Asynchronous as Async import qualified Control.Monad.Exception.Synchronous as Sync import Control.Applicative (WrappedMonad(WrapMonad), unwrapMonad, ) import Control.Monad (liftM, ) import Data.Monoid (Monoid, mappend, ) import Prelude hiding (map, ) type AsyncExceptionalT e m a = m (Async.Exceptional e a) -- in contrast to 'fmap' it does require Monad instance, not Functor map :: (Monad m) => (a -> b) -> Async.ExceptionalT body m a -> Async.ExceptionalT body m b map f = Async.mapExceptionalT unwrapMonad . fmap f . Async.mapExceptionalT WrapMonad infixr 1 `bind`, `append`, `continue` bind :: (Monad m, Monoid b) => Sync.ExceptionalT e m a -> (a -> AsyncExceptionalT e m b) -> AsyncExceptionalT e m b bind x y = Sync.tryT x >>= \result -> liftM Async.force (case result of Sync.Exception e -> return $ Async.throwMonoid e Sync.Success s -> y s) append :: (Monad m, Monoid a) => Sync.ExceptionalT e m a -> AsyncExceptionalT e m a -> AsyncExceptionalT e m a append x y = bind x (\s -> liftM (fmap (mappend s)) y) {- liftM2 (\x0 y0 -> Async.fromSynchronousMonoid x0 `Async.append` y0) (Sync.tryT x) y -} continue :: (Monad m, Monoid a) => Sync.ExceptionalT e m () -> AsyncExceptionalT e m a -> AsyncExceptionalT e m a continue x y = bind x (\_s -> y) {- liftM2 (\x0 y0 -> Sync.getExceptionNull x0 `Async.continue` y0) (Sync.tryT x) y -} switch :: Async.Exceptional e a -> (a -> b) -> (a -> Async.Exceptional e b) -> Async.Exceptional e b switch ea@(Async.Exceptional mea a) exception success = case mea of Just _ -> fmap exception ea Nothing -> success a switchM :: (Monad m) => m (Async.Exceptional e a) -> (a -> m b) -> (a -> m (Async.Exceptional e b)) -> m (Async.Exceptional e b) switchM actA exception success = do ea@(Async.Exceptional mea a) <- actA case mea of Just _ -> Async.mapM exception ea Nothing -> success a