packages feed

control-monad-exception 0.10.3.1 → 0.11.1

raw patch · 7 files changed

+501/−277 lines, 7 filesdep +lifted-basedep +monad-controldep +transformers-basePVP ok

version bump matches the API change (PVP)

Dependencies added: lifted-base, monad-control, transformers-base

API changes (from Hackage documentation)

- Control.Monad.Exception: EMT :: m (Either (CallTrace, CheckedException l) a) -> EMT l m a
- Control.Monad.Exception: FailException :: String -> FailException
- Control.Monad.Exception: MonadZeroException :: MonadZeroException
- Control.Monad.Exception: SomeException :: e -> SomeException
- Control.Monad.Exception: bracket :: Monad m => EMT l m a -> (a -> EMT l m b) -> (a -> EMT l m c) -> EMT l m c
- Control.Monad.Exception: catch :: (Exception e, Monad m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a
- Control.Monad.Exception: catchWithSrcLoc :: (Exception e, Monad m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a
- Control.Monad.Exception: class (Typeable e, Show e) => Exception e
- Control.Monad.Exception: class Monad f => Failure e (f :: * -> *)
- Control.Monad.Exception: class Monad m => MonadLoc (m :: * -> *)
- Control.Monad.Exception: class Exception e => Throws e l
- Control.Monad.Exception: class Typeable a
- Control.Monad.Exception: class Exception e => UncaughtException e
- Control.Monad.Exception: data AnyException
- Control.Monad.Exception: data Caught e l
- Control.Monad.Exception: data FailException
- Control.Monad.Exception: data MonadZeroException
- Control.Monad.Exception: data SomeException :: *
- Control.Monad.Exception: failure :: Failure e f => e -> f v
- Control.Monad.Exception: finally :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
- Control.Monad.Exception: fromException :: Exception e => SomeException -> Maybe e
- Control.Monad.Exception: mplusDefault :: Monad m => EMT l m a -> EMT l m a -> EMT l m a
- Control.Monad.Exception: newtype EMT l m a
- Control.Monad.Exception: onException :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
- Control.Monad.Exception: rethrow :: (Throws e l, Monad m) => CallTrace -> e -> EMT l m a
- Control.Monad.Exception: runEM :: EM NoExceptions a -> a
- Control.Monad.Exception: runEMParanoid :: EM ParanoidMode a -> a
- Control.Monad.Exception: runEMT :: Monad m => EMT NoExceptions m a -> m a
- Control.Monad.Exception: runEMTParanoid :: Monad m => EMT ParanoidMode m a -> m a
- Control.Monad.Exception: showExceptionWithTrace :: Exception e => [String] -> e -> String
- Control.Monad.Exception: throw :: (Exception e, Throws e l, Monad m) => e -> EMT l m a
- Control.Monad.Exception: toException :: Exception e => e -> SomeException
- Control.Monad.Exception: tryEM :: EM AnyException a -> Either SomeException a
- Control.Monad.Exception: tryEMT :: Monad m => EMT AnyException m a -> m (Either SomeException a)
- Control.Monad.Exception: type CallTrace = [String]
- Control.Monad.Exception: type EM l = EMT l Identity
- Control.Monad.Exception: typeOf :: Typeable a => a -> TypeRep
- Control.Monad.Exception: unEMT :: EMT l m a -> m (Either (CallTrace, CheckedException l) a)
- Control.Monad.Exception: withLoc :: MonadLoc m => String -> m a -> m a
- Control.Monad.Exception: withLocTH :: Q Exp
- Control.Monad.Exception: wrapException :: (Exception e, Throws e' l, Monad m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a
- Control.Monad.Exception.Base: bracket :: Monad m => EMT l m a -> (a -> EMT l m b) -> (a -> EMT l m c) -> EMT l m c
- Control.Monad.Exception.Base: catch :: (Exception e, Monad m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a
- Control.Monad.Exception.Base: catchWithSrcLoc :: (Exception e, Monad m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a
- Control.Monad.Exception.Base: finally :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
- Control.Monad.Exception.Base: instance [overlap ok] (Exception e, Monad m) => MonadCatch e (EMT (Caught e l) m) (EMT l m)
- Control.Monad.Exception.Base: instance [overlap ok] (Throws SomeException l, MonadIO m) => MonadIO (EMT l m)
- Control.Monad.Exception.Base: onException :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
- Control.Monad.Exception.Base: runEMT_gen :: Monad m => EMT l m a -> m a
- Control.Monad.Exception.Base: wrapException :: (Exception e, Throws e' l, Monad m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a
+ Control.Monad.Exception.Base: instance [overlap ok] MonadBase b m => MonadBase b (EMT l m)
+ Control.Monad.Exception.Base: instance [overlap ok] MonadBaseControl b m => MonadBaseControl b (EMT l m)
+ Control.Monad.Exception.Base: instance [overlap ok] MonadIO m => MonadIO (EMT l m)
+ Control.Monad.Exception.Base: instance [overlap ok] MonadTransControl (EMT l)
+ Control.Monad.Exception.Base: instance [overlap ok] Throws MonadZeroException l => Alternative (EM l)
+ Control.Monad.Exception.Base: runEMTGen :: Monad m => EMT l m a -> m a
+ Control.Monad.Exception.IO: EMT :: m (Either (CallTrace, CheckedException l) a) -> EMT l m a
+ Control.Monad.Exception.IO: FailException :: String -> FailException
+ Control.Monad.Exception.IO: MonadZeroException :: MonadZeroException
+ Control.Monad.Exception.IO: SomeException :: e -> SomeException
+ Control.Monad.Exception.IO: bracket :: MonadBaseControl IO m => EMT l m a -> (a -> EMT l m b) -> (a -> EMT l m c) -> EMT l m c
+ Control.Monad.Exception.IO: catch :: (Exception e, MonadBaseControl IO m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a
+ Control.Monad.Exception.IO: catchWithSrcLoc :: (Exception e, MonadBaseControl IO m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a
+ Control.Monad.Exception.IO: class (Typeable e, Show e) => Exception e
+ Control.Monad.Exception.IO: class Monad f => Failure e (f :: * -> *)
+ Control.Monad.Exception.IO: class Exception e => Throws e l
+ Control.Monad.Exception.IO: class Typeable a
+ Control.Monad.Exception.IO: class Exception e => UncaughtException e
+ Control.Monad.Exception.IO: data AnyException
+ Control.Monad.Exception.IO: data Caught e l
+ Control.Monad.Exception.IO: data FailException
+ Control.Monad.Exception.IO: data MonadZeroException
+ Control.Monad.Exception.IO: data SomeException :: *
+ Control.Monad.Exception.IO: failure :: Failure e f => e -> f v
+ Control.Monad.Exception.IO: finally :: MonadBaseControl IO m => EMT l m a -> EMT l m b -> EMT l m a
+ Control.Monad.Exception.IO: fromException :: Exception e => SomeException -> Maybe e
+ Control.Monad.Exception.IO: instance [overlap ok] (Exception e, MonadBaseControl IO m) => MonadCatch e (EMT (Caught e l) m) (EMT l m)
+ Control.Monad.Exception.IO: mplusDefault :: Monad m => EMT l m a -> EMT l m a -> EMT l m a
+ Control.Monad.Exception.IO: newtype EMT l m a
+ Control.Monad.Exception.IO: onException :: MonadBaseControl IO m => EMT l m a -> EMT l m b -> EMT l m a
+ Control.Monad.Exception.IO: rethrow :: (Throws e l, Monad m) => CallTrace -> e -> EMT l m a
+ Control.Monad.Exception.IO: runEM :: EM NoExceptions a -> a
+ Control.Monad.Exception.IO: runEMParanoid :: EM ParanoidMode a -> a
+ Control.Monad.Exception.IO: runEMT :: Monad m => EMT NoExceptions m a -> m a
+ Control.Monad.Exception.IO: runEMTParanoid :: Monad m => EMT ParanoidMode m a -> m a
+ Control.Monad.Exception.IO: showExceptionWithTrace :: Exception e => [String] -> e -> String
+ Control.Monad.Exception.IO: throw :: (Exception e, Throws e l, Monad m) => e -> EMT l m a
+ Control.Monad.Exception.IO: toException :: Exception e => e -> SomeException
+ Control.Monad.Exception.IO: tryEM :: EM AnyException a -> Either SomeException a
+ Control.Monad.Exception.IO: tryEMT :: Monad m => EMT AnyException m a -> m (Either SomeException a)
+ Control.Monad.Exception.IO: tryEMTWithLoc :: Monad m => EMT AnyException m a -> m (Either (CallTrace, SomeException) a)
+ Control.Monad.Exception.IO: tryEMWithLoc :: EM AnyException a -> Either (CallTrace, SomeException) a
+ Control.Monad.Exception.IO: type CallTrace = [String]
+ Control.Monad.Exception.IO: type EM l = EMT l Identity
+ Control.Monad.Exception.IO: unEMT :: EMT l m a -> m (Either (CallTrace, CheckedException l) a)
+ Control.Monad.Exception.IO: wrapException :: (Exception e, Throws e' l, MonadBaseControl IO m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a
+ Control.Monad.Exception.Pure: EMT :: m (Either (CallTrace, CheckedException l) a) -> EMT l m a
+ Control.Monad.Exception.Pure: FailException :: String -> FailException
+ Control.Monad.Exception.Pure: MonadZeroException :: MonadZeroException
+ Control.Monad.Exception.Pure: SomeException :: e -> SomeException
+ Control.Monad.Exception.Pure: bracket :: Monad m => EMT l m a -> (a -> EMT l m b) -> (a -> EMT l m c) -> EMT l m c
+ Control.Monad.Exception.Pure: catch :: (Exception e, Monad m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a
+ Control.Monad.Exception.Pure: catchWithSrcLoc :: (Exception e, Monad m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a
+ Control.Monad.Exception.Pure: class (Typeable e, Show e) => Exception e
+ Control.Monad.Exception.Pure: class Monad f => Failure e (f :: * -> *)
+ Control.Monad.Exception.Pure: class Exception e => Throws e l
+ Control.Monad.Exception.Pure: class Typeable1 (t :: * -> *)
+ Control.Monad.Exception.Pure: class Exception e => UncaughtException e
+ Control.Monad.Exception.Pure: data AnyException
+ Control.Monad.Exception.Pure: data Caught e l
+ Control.Monad.Exception.Pure: data FailException
+ Control.Monad.Exception.Pure: data MonadZeroException
+ Control.Monad.Exception.Pure: data SomeException :: *
+ Control.Monad.Exception.Pure: failure :: Failure e f => e -> f v
+ Control.Monad.Exception.Pure: finally :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
+ Control.Monad.Exception.Pure: fromException :: Exception e => SomeException -> Maybe e
+ Control.Monad.Exception.Pure: instance [overlap ok] (Exception e, Monad m) => MonadCatch e (EMT (Caught e l) m) (EMT l m)
+ Control.Monad.Exception.Pure: mplusDefault :: Monad m => EMT l m a -> EMT l m a -> EMT l m a
+ Control.Monad.Exception.Pure: newtype EMT l m a
+ Control.Monad.Exception.Pure: onException :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
+ Control.Monad.Exception.Pure: rethrow :: (Throws e l, Monad m) => CallTrace -> e -> EMT l m a
+ Control.Monad.Exception.Pure: runEM :: EM NoExceptions a -> a
+ Control.Monad.Exception.Pure: runEMParanoid :: EM ParanoidMode a -> a
+ Control.Monad.Exception.Pure: runEMT :: Monad m => EMT NoExceptions m a -> m a
+ Control.Monad.Exception.Pure: runEMTParanoid :: Monad m => EMT ParanoidMode m a -> m a
+ Control.Monad.Exception.Pure: showExceptionWithTrace :: Exception e => [String] -> e -> String
+ Control.Monad.Exception.Pure: throw :: (Exception e, Throws e l, Monad m) => e -> EMT l m a
+ Control.Monad.Exception.Pure: toException :: Exception e => e -> SomeException
+ Control.Monad.Exception.Pure: tryEM :: EM AnyException a -> Either SomeException a
+ Control.Monad.Exception.Pure: tryEMT :: Monad m => EMT AnyException m a -> m (Either SomeException a)
+ Control.Monad.Exception.Pure: tryEMTWithLoc :: Monad m => EMT AnyException m a -> m (Either (CallTrace, SomeException) a)
+ Control.Monad.Exception.Pure: tryEMWithLoc :: EM AnyException a -> Either (CallTrace, SomeException) a
+ Control.Monad.Exception.Pure: type CallTrace = [String]
+ Control.Monad.Exception.Pure: type EM l = EMT l Identity
+ Control.Monad.Exception.Pure: unEMT :: EMT l m a -> m (Either (CallTrace, CheckedException l) a)
+ Control.Monad.Exception.Pure: wrapException :: (Exception e, Throws e' l, Monad m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a

Files

Control/Monad/Exception.hs view
@@ -1,171 +1,15 @@-{-# LANGUAGE CPP #-}  {-| A Monad Transformer for explicitly typed checked exceptions, described in detail by: -  * Jose Iborra, \"Explicitly Typed Exceptions for Haskell",-    PADL'10, January 2010, <http://safe-tools.dsic.upv.es/mediawiki/index.php/Jose_Iborra/Papers/Exceptions>--The exceptions thrown by a computation are inferred by the typechecker-and appear in the type signature of the computation as 'Throws' constraints.--Exceptions are defined using the extensible exceptions framework of Marlow (documented in "Control.Exception"):-- * /An Extensible Dynamically-Typed Hierarchy of Exceptions/, by Simon Marlow, in /Haskell '06/.--  /Example/--  > data DivideByZero = DivideByZero deriving (Show, Typeable)-  > data SumOverflow  = SumOverflow  deriving (Show, Typeable)-  -  > instance Exception DivideByZero-  > instance Exception SumOverflow-  -  > data Expr = Add Expr Expr | Div Expr Expr | Val Double--  > eval (Val x)     = return x-  > eval (Add a1 a2) = do-  >    v1 <- eval a1-  >    v2 <- eval a2-  >    let sum = v1 + v2-  >    if sum < v1 || sum < v2 then throw SumOverflow else return sum-  > eval (Div a1 a2) = do-  >    v1 <- eval a1-  >    v2 <- eval a2-  >    if v2 == 0 then throw DivideByZero else return (v1 / v2)--  GHCi infers the following types-  -  > eval                                             :: (Throws DivideByZero l, Throws SumOverflow l) => Expr -> EM l Double-  > eval `catch` \ (e::DivideByZero) -> return (-1)  :: Throws SumOverflow l => Expr -> EM l Double-  > runEM(eval `catch` \ (e::SomeException) -> return (-1))-  >                                                  :: Expr -> Double--}--module Control.Monad.Exception (--- * Important trivia--- ** Hierarchies of Exceptions--- $hierarchies---- ** Unchecked exceptions--- *** Unchecked exceptions--- $unchecked---- ** Stack Traces--- $stacktraces---- ** Understanding GHC errors--- $errors---- * The EM monad-    EM,  tryEM, runEM, runEMParanoid,---- * The EMT monad transformer-    EMT(..), CallTrace, tryEMT, runEMT, runEMTParanoid, AnyException, UncaughtException,---- ** The Throws type class-   Throws, Caught,---- * Exception primitives-      throw, rethrow, Control.Monad.Exception.Base.catch, Control.Monad.Exception.Base.catchWithSrcLoc,-    finally, onException, bracket, wrapException,--    showExceptionWithTrace,-    FailException(..), MonadZeroException(..), mplusDefault,---- * Reexports-    Exception(..), SomeException(..), Typeable(..),-    Failure(..),-#if !MIN_VERSION_failure(0,2,0)-    Try(..), NothingException(..),-    WrapFailure(..),-#endif-    MonadLoc(..), withLocTH-) where--import Control.Monad.Exception.Base-import Control.Monad.Exception.Catch-import Control.Failure-import Control.Monad.Loc-import Control.Monad.Loc.TH-import Data.Typeable--{- $hierarchies- If your sets of exceptions are hierarchical then you need to-   teach 'Throws' about the hierarchy. See the documentation of-   'Throws' for more info.--}-{- $unchecked-An exception @E@ can be declared as unchecked by making @E@ an instance of-   'UncaughtException'.--> instance UncaughtException E--   @E@ will still appear in the list of exceptions thrown-   by a computation but 'runEMT' will not complain if @E@ escapes the computation-   being run.--Also, 'tryEMT' allows you to run a computation regardless of the exceptions it throws.--}---{- $stacktraces- Stack traces are provided via the "MonadLoc" package.-   All you need to do is add the following pragma at the top of your Haskell-   source files and use do-notation:-->  { # OPTIONS_GHC -F -pgmF MonadLoc # }--   Only statements in do blocks appear in the stack trace.--   Example:-->       f () = do throw MyException->       g a  = do f a->->       main = runEMT $ do->                g () `catchWithSrcLoc`->                        \loc (e::MyException) -> lift(putStrLn$ showExceptionWithTrace loc e)-->        -- Running main produces the output:-->       *Main> main->       MyException->        in f, Main(example.hs): (1,6)->           g, Main(example.hs): (2,6)->           main, Main(example.hs): (5,9)->           main, Main(example.hs): (4,16)+  * Jose Iborra, \"Explicitly Typed Exceptions for Haskell\",+    PADL'10, January 2010, <http://dl.dropbox.com/s/lgm12trtl0swtra/PADL10.pdf?dl=1> +"Control.Monad.Exception.Pure" provides the classic, Either based monad,+whereas "Control.Monad.Exception.IO" provides a more advanced IO based monad with+the ability to handle asynchronous exceptions as well. -} --{- $errors-A type error of the form:-->    No instance for (UncaughtException MyException)->      arising from a use of `g' at examples/docatch.hs:21:32-35->    Possible fix:->      add an instance declaration for (UncaughtException MyException)->    In the expression: g ()--is the type checker saying:--\"hey, you are trying to run a computation which throws a @MyException@ without handling it, and I won't let you\"--Either handle it or declare @MyException@ as an 'UncaughtException'.--A type error of the form:-->    Overlapping instances for Throws MyException (Caught e NoExceptions)->      arising from a use of `g' at docatch.hs:24:3-6->    Matching instances:->      instance (Throws e l) => Throws e (Caught e' l)->        -- Defined at ../Control/Monad/Exception/Throws.hs:46:9-45->      instance (Exception e) => Throws e (Caught e l)->        -- Defined at ../Control/Monad/Exception/Throws.hs:47:9-44->    (The choice depends on the instantiation of `e'->    ...+module Control.Monad.Exception ( module Control.Monad.Exception.Pure ) where -is due to an exception handler for @MyException@-missing a type annotation to pin down the type of the exception.--}+import Control.Monad.Exception.Pure
Control/Monad/Exception/Base.hs view
@@ -5,52 +5,15 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE OverlappingInstances #-}--{-|-A Monad Transformer for explicitly typed checked exceptions.--The exceptions thrown by a computation are inferred by the typechecker-and appear in the type signature of the computation as 'Throws' constraints.--Exceptions are defined using the extensible exceptions framework of Marlow (documented in "Control.Exception"):-- * /An Extensible Dynamically-Typed Hierarchy of Exceptions/, by Simon Marlow, in /Haskell '06/.--  /Example/--  > data DivideByZero = DivideByZero deriving (Show, Typeable)-  > data SumOverflow  = SumOverflow  deriving (Show, Typeable)-  -  > instance Exception DivideByZero-  > instance Exception SumOverflow-  -  > data Expr = Add Expr Expr | Div Expr Expr | Val Double--  > eval (Val x)     = return x-  > eval (Add a1 a2) = do-  >    v1 <- eval a1-  >    v2 <- eval a2-  >    let sum = v1 + v2-  >    if sum < v1 || sum < v2 then throw SumOverflow else return sum-  > eval (Div a1 a2) = do-  >    v1 <- eval a1-  >    v2 <- eval a2-  >    if v2 == 0 then throw DivideByZero else return (v1 / v2)--  GHCi infers the following types-  -  > eval                                             :: (Throws DivideByZero l, Throws SumOverflow l) => Expr -> EM l Double-  > eval `catch` \ (e::DivideByZero) -> return (-1)  :: Throws SumOverflow l => Expr -> EM l Double-  > runEM(eval `catch` \ (e::SomeException) -> return (-1))-  >                                                  :: Expr -> Double--} module Control.Monad.Exception.Base where -import qualified Control.Exception as CE import Control.Applicative+import Control.Arrow+import Control.Monad.Base import Control.Monad.Exception.Catch import Control.Monad.Loc import Control.Monad.Trans.Class+import Control.Monad.Trans.Control import Control.Monad.IO.Class import Control.Failure import Control.Monad.Fix@@ -67,10 +30,10 @@ tryEMT (EMT m) = mapLeft (checkedException.snd) `liftM` m  tryEMTWithLoc :: Monad m => EMT AnyException m a -> m (Either (CallTrace, SomeException) a)-tryEMTWithLoc = liftM (mapLeft (\(l,ce) -> (l, checkedException ce))) . unEMT+tryEMTWithLoc = liftM (mapLeft (second checkedException)) . unEMT -runEMT_gen :: forall l m a . Monad m => EMT l m a -> m a-runEMT_gen (EMT m) = m >>= \x ->+runEMTGen :: forall l m a . Monad m => EMT l m a -> m a+runEMTGen (EMT m) = m >>= \x ->                      case x of                        Right x -> return x                        Left (loc,e) -> error (showExceptionWithTrace loc (checkedException e))@@ -83,11 +46,11 @@  -- | Run a safe computation runEMT :: Monad m => EMT NoExceptions m a -> m a-runEMT = runEMT_gen+runEMT = runEMTGen  -- | Run a safe computation checking even unchecked ('UncaughtException') exceptions runEMTParanoid :: Monad m => EMT ParanoidMode m a -> m a-runEMTParanoid = runEMT_gen+runEMTParanoid = runEMTGen  instance Monad m => Functor (EMT l m) where   fmap f emt = EMT $ do@@ -128,10 +91,20 @@ instance MonadTrans (EMT l) where   lift = EMT . liftM Right -instance (Exception e, Monad m) => MonadCatch e (EMT (Caught e l) m) (EMT l m) where-  catchWithSrcLoc = Control.Monad.Exception.Base.catchWithSrcLoc-  catch           = Control.Monad.Exception.Base.catch +instance MonadBase b m => MonadBase b (EMT l m) where+    liftBase = liftBaseDefault++instance MonadBaseControl b m => MonadBaseControl b (EMT l m) where+     newtype StM (EMT l m) a = StmEMT {unStmEMT :: ComposeSt (EMT l) m a}+     liftBaseWith = defaultLiftBaseWith StmEMT+     restoreM     = defaultRestoreM   unStmEMT++instance MonadTransControl (EMT l) where+     newtype StT (EMT l) a = StEMT {unStEMT :: Either (CallTrace, CheckedException l) a}+     liftWith f = EMT $ liftM return $ f $ liftM StEMT . unEMT+     restoreT       = EMT . liftM unStEMT+ instance Monad m => MonadLoc (EMT l m) where     withLoc loc (EMT emt) = EMT $ do                      current <- withLoc loc emt@@ -152,49 +125,6 @@ rethrow :: (Throws e l, Monad m) => CallTrace -> e -> EMT l m a rethrow callt = EMT . return . (\e -> Left (callt,e)) . CheckedException . toException ---- | The catch primitive-catch :: (Exception e, Monad m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a-catch emt h = Control.Monad.Exception.Base.catchWithSrcLoc emt (\_ -> h)---- | Like 'Control.Monad.Exception.Base.catch' but makes the call trace available-catchWithSrcLoc :: (Exception e, Monad m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a-catchWithSrcLoc emt h = EMT $ do-                v <- unEMT emt-                case v of-                  Right x -> return (Right x)-                  Left (trace, CheckedException e) -> case fromException e of-                               Nothing -> return (Left (trace,CheckedException e))-                               Just e' -> unEMT (h trace e')----- | Sequence two computations discarding the result of the second one.---   If the first computation rises an exception, the second computation is run---   and then the exception is rethrown.-finally :: Monad m => EMT l m a -> EMT l m b -> EMT l m a-finally m sequel = do { v <- m `onException` sequel; _ <- sequel; return v}----- | Like finally, but performs the second computation only when the first one---   rises an exception-onException :: Monad m => EMT l m a -> EMT l m b -> EMT l m a-onException (EMT m) (EMT sequel) = EMT $ do-                                     ev <- m-                                     case ev of-                                       Left{}  -> do { _ <- sequel; return ev}-                                       Right{} -> return ev--bracket :: Monad m => EMT l m a        -- ^ acquire resource-                   -> (a -> EMT l m b) -- ^ release resource-                   -> (a -> EMT l m c) -- ^ computation-                   -> EMT l m c-bracket acquire release run = do { k <- acquire; run k `finally` (release k) }---- | Capture an exception e, wrap it, and rethrow.---   Keeps the original monadic call trace.-wrapException :: (Exception e, Throws e' l, Monad m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a-wrapException mkE m = m `Control.Monad.Exception.Base.catchWithSrcLoc` \loc e -> rethrow loc (mkE e)- showExceptionWithTrace :: Exception e => [String] -> e -> String showExceptionWithTrace [] e = show e showExceptionWithTrace trace e = unlines ( show e@@ -240,6 +170,9 @@   mzero = throw MonadZeroException   mplus = mplusDefault +instance (Throws MonadZeroException l) => Alternative (EM l) where+  (<|>) = mplus+  empty = mzero -- ----------- -- Exceptions -- -----------@@ -266,8 +199,5 @@ mapLeft _ (Right x) = Right x  -instance (Throws SomeException l, MonadIO m) => MonadIO (EMT l m) where-  liftIO m = EMT (liftIO m') where-      m' = liftM Right m-            `CE.catch`-           \(e::SomeException) -> return (Left ([], CheckedException e))+instance MonadIO m => MonadIO (EMT l m) where+  liftIO = lift . liftIO
Control/Monad/Exception/Catch.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE FlexibleInstances #-}
+ Control/Monad/Exception/IO.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE CPP #-}++{-|+A monad transformer for explicitly typed checked exceptions with support for asynchronous exception handling. Explicit exceptions are supported by the ideas described in:++  * Jose Iborra, \"Explicitly Typed Exceptions for Haskell\",+    PADL'10, January 2010, <http://dl.dropbox.com/s/lgm12trtl0swtra/PADL10.pdf?dl=1>++The exceptions thrown by a computation are inferred by the typechecker+and appear in the type signature of the computation as 'Throws' constraints.++Support for asynchronous exceptions is provided by the monad-control package.++  /Example/++  > data DivideByZero = DivideByZero deriving (Show, Typeable)+  > data SumOverflow  = SumOverflow  deriving (Show, Typeable)+  +  > instance Exception DivideByZero+  > instance Exception SumOverflow+  +  > data Expr = Add Expr Expr | Div Expr Expr | Val Double++  > eval (Val x)     = return x+  > eval (Add a1 a2) = do+  >    v1 <- eval a1+  >    v2 <- eval a2+  >    let sum = v1 + v2+  >    if sum < v1 || sum < v2 then throw SumOverflow else return sum+  > eval (Div a1 a2) = do+  >    v1 <- eval a1+  >    v2 <- eval a2+  >    if v2 == 0 then throw DivideByZero else return (v1 / v2)++  GHCi infers the following types+  +  > eval                                             :: (Throws DivideByZero l, Throws SumOverflow l) => Expr -> EM l Double+  > eval `catch` \ (e::DivideByZero) -> return (-1)  :: Throws SumOverflow l => Expr -> EM l Double+  > runEM(eval `catch` \ (e::SomeException) -> return (-1))+  >                                                  :: Expr -> Double+-}++module Control.Monad.Exception.IO (+-- * Important trivia+-- ** Hierarchies of Exceptions+-- $hierarchies++-- ** Unchecked exceptions+-- *** Unchecked exceptions+-- $unchecked++-- ** Stack Traces+-- $stacktraces++-- ** Understanding GHC errors+-- $errors++-- * The EM monad+    EM,  tryEM, tryEMWithLoc, runEM, runEMParanoid,++-- * The EMT monad transformer+    EMT(..), CallTrace, tryEMT, tryEMTWithLoc, runEMT, runEMTParanoid, AnyException, UncaughtException,++-- ** The Throws type class+   Throws, Caught,++-- * Exception primitives+      throw, rethrow, catch, catchWithSrcLoc,+    finally, onException, bracket, wrapException,++    showExceptionWithTrace,+    FailException(..), MonadZeroException(..), mplusDefault,++-- * Reexports+    Exception(..), SomeException(..), Typeable,+    Failure(..),+#if !MIN_VERSION_failure(0,2,0)+    Try(..), NothingException(..),+    WrapFailure(..),+#endif+) where++import Control.Monad.Exception.Base+import Control.Monad.Exception.Throws+import Control.Monad.Exception.Catch (Exception, SomeException, fromException, MonadCatch)+import qualified Control.Monad.Exception.Catch+import Control.Failure+import Control.Monad.Trans.Control+import Data.Typeable+import Control.Exception.Lifted as CE (try)++{- $hierarchies+ If exceptions are hierarchical then you need to+   teach 'Throws' about the hierarchy. See the documentation of+   'Throws' for more info.+-}+{- $unchecked+An exception @E@ can be declared as unchecked by making @E@ an instance of+   'UncaughtException'.++> instance UncaughtException E++   @E@ will still appear in the list of exceptions thrown+   by a computation but 'runEMT' will not complain if @E@ escapes the computation+   being run.++Also, 'tryEMT' allows you to run a computation regardless of the exceptions it throws.+-}+++{- $stacktraces+ Stack traces are provided via the "MonadLoc" package.+   All you need to do is add the following pragma at the top of your Haskell+   source files and use do-notation:++>  { # OPTIONS_GHC -F -pgmF MonadLoc # }++   Only statements in do blocks appear in the stack trace.++   Example:++>       f () = do throw MyException+>       g a  = do f a+>+>       main = runEMT $ do+>                g () `catchWithSrcLoc`+>                        \loc (e::MyException) -> lift(putStrLn$ showExceptionWithTrace loc e)++>        -- Running main produces the output:++>       *Main> main+>       MyException+>        in f, Main(example.hs): (1,6)+>           g, Main(example.hs): (2,6)+>           main, Main(example.hs): (5,9)+>           main, Main(example.hs): (4,16)++-}+++{- $errors+A type error of the form:++>    No instance for (UncaughtException MyException)+>      arising from a use of `g' at examples/docatch.hs:21:32-35+>    Possible fix:+>      add an instance declaration for (UncaughtException MyException)+>    In the expression: g ()++is the type checker saying:++\"hey, you are trying to run a computation which throws a @MyException@ without handling it, and I won't let you\"++Either handle it or declare @MyException@ as an 'UncaughtException'.++A type error of the form:++>    Overlapping instances for Throws MyException (Caught e NoExceptions)+>      arising from a use of `g' at docatch.hs:24:3-6+>    Matching instances:+>      instance (Throws e l) => Throws e (Caught e' l)+>        -- Defined at ../Control/Monad/Exception/Throws.hs:46:9-45+>      instance (Exception e) => Throws e (Caught e l)+>        -- Defined at ../Control/Monad/Exception/Throws.hs:47:9-44+>    (The choice depends on the instantiation of `e'+>    ...++is due to an exception handler for @MyException@+missing a type annotation to pin down the type of the exception.+-}+++-- | The catch primitive+catch :: (Exception e, MonadBaseControl IO m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a+catch emt h = catchWithSrcLoc emt (const h)++unwrap :: MonadBaseControl IO m => EMT l m a -> m (Either (CallTrace, CheckedException l) a)+unwrap m = do+  v <- CE.try $ unEMT m+  case v of+    Right x -> return x+    Left  e -> return (Left ([], CheckedException e))++-- | Catch and exception and observe the stack trace.+--   If on top of the IO monad, this will also capture asynchronous exceptions+catchWithSrcLoc :: (Exception e, MonadBaseControl IO m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a+catchWithSrcLoc emt h = EMT $ do+                v <- unwrap emt+                case v of+                  Right x -> return (Right x)+                  Left (trace, CheckedException e) -> handle e trace+       where handle e trace =+                      case fromException e of+                               Nothing -> return (Left (trace,CheckedException e))+                               Just e' -> unEMT (h trace e')++instance (Exception e, MonadBaseControl IO m) => MonadCatch e (EMT (Caught e l) m) (EMT l m) where+  catchWithSrcLoc = catchWithSrcLoc+  catch           = catch++-- | Sequence two computations discarding the result of the second one.+--   If the first computation rises an exception, the second computation is run+--   and then the exception is rethrown.+finally :: MonadBaseControl IO m => EMT l m a -> EMT l m b -> EMT l m a+finally m sequel = do { v <- m `onException` sequel; _ <- sequel; return v}+++-- | Like finally, but performs the second computation only when the first one+--   rises an exception+onException :: MonadBaseControl IO m => EMT l m a -> EMT l m b -> EMT l m a+onException m sequel = EMT $ do+                         ev <- unwrap m+                         case ev of+                           Left{}  -> do { _ <- unEMT sequel; return ev}+                           Right{} -> return ev++bracket :: MonadBaseControl IO m =>+                   EMT l m a        -- ^ acquire resource+                   -> (a -> EMT l m b) -- ^ release resource+                   -> (a -> EMT l m c) -- ^ computation+                   -> EMT l m c+bracket acquire release run = do { k <- acquire; run k `finally` release k }+++-- | Capture an exception e, wrap it, and rethrow.+--   Keeps the original monadic call trace.+wrapException :: (Exception e, Throws e' l, MonadBaseControl IO m) =>+                 (e -> e') -> EMT (Caught e l) m a -> EMT l m a+wrapException mkE m = m `catchWithSrcLoc` \loc e -> rethrow loc (mkE e)
+ Control/Monad/Exception/Pure.hs view
@@ -0,0 +1,221 @@+{-# LANGUAGE CPP #-}++{-|+A Monad Transformer for explicitly typed checked exceptions, described in detail by:++  * Jose Iborra, \"Explicitly Typed Exceptions for Haskell\",+    PADL'10, January 2010, <http://dl.dropbox.com/s/lgm12trtl0swtra/PADL10.pdf?dl=1>++The exceptions thrown by a computation are inferred by the typechecker+and appear in the type signature of the computation as 'Throws' constraints.++Exceptions are defined using the extensible exceptions framework of Marlow (documented in "Control.Exception"):++ * /An Extensible Dynamically-Typed Hierarchy of Exceptions/, by Simon Marlow, in /Haskell '06/.++  /Example/++  > data DivideByZero = DivideByZero deriving (Show, Typeable)+  > data SumOverflow  = SumOverflow  deriving (Show, Typeable)+  +  > instance Exception DivideByZero+  > instance Exception SumOverflow+  +  > data Expr = Add Expr Expr | Div Expr Expr | Val Double++  > eval (Val x)     = return x+  > eval (Add a1 a2) = do+  >    v1 <- eval a1+  >    v2 <- eval a2+  >    let sum = v1 + v2+  >    if sum < v1 || sum < v2 then throw SumOverflow else return sum+  > eval (Div a1 a2) = do+  >    v1 <- eval a1+  >    v2 <- eval a2+  >    if v2 == 0 then throw DivideByZero else return (v1 / v2)++  GHCi infers the following types+  +  > eval                                             :: (Throws DivideByZero l, Throws SumOverflow l) => Expr -> EM l Double+  > eval `catch` \ (e::DivideByZero) -> return (-1)  :: Throws SumOverflow l => Expr -> EM l Double+  > runEM(eval `catch` \ (e::SomeException) -> return (-1))+  >                                                  :: Expr -> Double+-}++module Control.Monad.Exception.Pure (+-- * Important trivia+-- ** Hierarchies of Exceptions+-- $hierarchies++-- ** Unchecked exceptions+-- *** Unchecked exceptions+-- $unchecked++-- ** Stack Traces+-- $stacktraces++-- ** Understanding GHC errors+-- $errors++-- * The EM monad+    EM,  tryEM, tryEMWithLoc, runEM, runEMParanoid,++-- * The EMT monad transformer+    EMT(..), CallTrace, tryEMT, tryEMTWithLoc, runEMT, runEMTParanoid, AnyException, UncaughtException,++-- ** The Throws type class+   Throws, Caught,++-- * Exception primitives+      throw, rethrow, catch, catchWithSrcLoc,+    finally, onException, bracket, wrapException,++    showExceptionWithTrace,+    FailException(..), MonadZeroException(..), mplusDefault,++-- * Reexports+    Exception(..), SomeException(..), Typeable1,+    Failure(..),+#if !MIN_VERSION_failure(0,2,0)+    Try(..), NothingException(..),+    WrapFailure(..),+#endif+) where++import Control.Monad.Exception.Base+import Control.Monad.Exception.Throws+import Control.Monad.Exception.Catch (MonadCatch, Exception, SomeException, fromException)+import qualified Control.Monad.Exception.Catch+import Control.Failure+import Data.Typeable++{- $hierarchies+ If your exceptions are hierarchical then you need to+   teach 'Throws' about the hierarchy. See the documentation of+   'Throws' for more info.+-}+{- $unchecked+An exception @E@ can be declared as unchecked by making @E@ an instance of+   'UncaughtException'.++> instance UncaughtException E++   @E@ will still appear in the list of exceptions thrown+   by a computation but 'runEMT' will not complain if @E@ escapes the computation+   being run.++Also, 'tryEMT' allows you to run a computation regardless of the exceptions it throws.+-}+++{- $stacktraces+ Stack traces are provided via the "MonadLoc" package.+   All you need to do is add the following pragma at the top of your Haskell+   source files and use do-notation:++>  { # OPTIONS_GHC -F -pgmF MonadLoc # }++   Only statements in do blocks appear in the stack trace.++   Example:++>       f () = do throw MyException+>       g a  = do f a+>+>       main = runEMT $ do+>                g () `catchWithSrcLoc`+>                        \loc (e::MyException) -> lift(putStrLn$ showExceptionWithTrace loc e)++>        -- Running main produces the output:++>       *Main> main+>       MyException+>        in f, Main(example.hs): (1,6)+>           g, Main(example.hs): (2,6)+>           main, Main(example.hs): (5,9)+>           main, Main(example.hs): (4,16)++-}+++{- $errors+A type error of the form:++>    No instance for (UncaughtException MyException)+>      arising from a use of `g' at examples/docatch.hs:21:32-35+>    Possible fix:+>      add an instance declaration for (UncaughtException MyException)+>    In the expression: g ()++is the type checker saying:++\"hey, you are trying to run a computation which throws a @MyException@ without handling it, and I won't let you\"++Either handle it or declare @MyException@ as an 'UncaughtException'.++A type error of the form:++>    Overlapping instances for Throws MyException (Caught e NoExceptions)+>      arising from a use of `g' at docatch.hs:24:3-6+>    Matching instances:+>      instance (Throws e l) => Throws e (Caught e' l)+>        -- Defined at ../Control/Monad/Exception/Throws.hs:46:9-45+>      instance (Exception e) => Throws e (Caught e l)+>        -- Defined at ../Control/Monad/Exception/Throws.hs:47:9-44+>    (The choice depends on the instantiation of `e'+>    ...++is due to an exception handler for @MyException@+missing a type annotation to pin down the type of the exception.+-}+++-- | The catch primitive+catch :: (Exception e, Monad m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a+catch emt h = catchWithSrcLoc emt (const h)++-- | Catch and exception and observe the stack trace.+--   If on top of the IO monad, this will also capture asynchronous exceptions+catchWithSrcLoc :: (Exception e, Monad m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a+catchWithSrcLoc emt h = EMT $ do+                v <- unEMT emt+                case v of+                  Right x -> return (Right x)+                  Left (trace, CheckedException e) -> handle e trace+       where handle e trace =+                      case fromException e of+                               Nothing -> return (Left (trace,CheckedException e))+                               Just e' -> unEMT (h trace e')++instance (Exception e, Monad m) => MonadCatch e (EMT (Caught e l) m) (EMT l m) where+  catchWithSrcLoc = catchWithSrcLoc+  catch           = catch++-- | Sequence two computations discarding the result of the second one.+--   If the first computation rises an exception, the second computation is run+--   and then the exception is rethrown.+finally :: Monad m => EMT l m a -> EMT l m b -> EMT l m a+finally m sequel = do { v <- m `onException` sequel; _ <- sequel; return v}+++-- | Like finally, but performs the second computation only when the first one+--   rises an exception+-- TODO asynchronous exceptions! This needs to be moved to Monad+onException :: Monad m => EMT l m a -> EMT l m b -> EMT l m a+onException (EMT m) (EMT sequel) = EMT $ do+                                     ev <- m+                                     case ev of+                                       Left{}  -> do { _ <- sequel; return ev}+                                       Right{} -> return ev++bracket :: Monad m => EMT l m a        -- ^ acquire resource+                   -> (a -> EMT l m b) -- ^ release resource+                   -> (a -> EMT l m c) -- ^ computation+                   -> EMT l m c+bracket acquire release run = do { k <- acquire; run k `finally` release k }+++-- | Capture an exception e, wrap it, and rethrow.+--   Keeps the original monadic call trace.+wrapException :: (Exception e, Throws e' l, Monad m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a+wrapException mkE m = m `catchWithSrcLoc` \loc e -> rethrow loc (mkE e)
+ changelog view
@@ -0,0 +1,8 @@+     * 0.9.0 - Moved to transformers (finally leaving the whole mtl-transformers cisma behind)+     * 0.10.0 - removed the dependency on safe-failure+     * 0.10.1 - compatibility with failure 0.2 (thanks to Bas van Dijk)+     * 0.10.2 - use the identity type from mtl (thanks to Bas), require minimum cabal-install version (thanks to Bernhard Urban)+     * 0.10.3 - Moved the MonadIO instance to the main package+     * 0.10.3.1 - Compatibility with base 4.6+     * 0.11 - Experimental support for asynchronous exceptions (via monad-control)+     * 0.11.1 - Add missing Alternative instances
control-monad-exception.cabal view
@@ -1,5 +1,5 @@ name: control-monad-exception-version: 0.10.3.1+version: 0.11.1 Cabal-Version:  >= 1.10 build-type: Simple license: PublicDomain@@ -38,7 +38,7 @@   > runEM(eval `catch` \ (e::SomeException) -> return (-1))  :: Expr -> Double   .   .-  In addition to explicitly typed exceptions his package provides:+  In addition to explicitly typed exceptions this package provides:   .     * Support for explicitly documented, unchecked exceptions (via 'Control.Monad.Exception.tryEMT').   .@@ -61,21 +61,6 @@   >       g, Main(example.hs): (2,6)   >       main, Main(example.hs): (5,9)   >       main, Main(example.hs): (4,16)-  .-  /Changes/:-  .-  .  -     * 0.9.0 - Moved to transformers (finally leaving the whole mtl-transformers cisma behind)-  .  -     * 0.10.0 - removed the dependency on safe-failure-  .  -     * 0.10.1 - compatibility with failure 0.2 (thanks to Bas van Dijk)-  .  -     * 0.10.2 - use the identity type from mtl (thanks to Bas), require minimum cabal-install version (thanks to Bernhard Urban)-  .-     * 0.10.3 - Moved the MonadIO instance to the main package-  .-     * 0.10.3.1 - Compatibility with base 4.6  synopsis: Explicitly typed, checked exceptions with stack traces category: Control, Monads, Failure@@ -83,6 +68,9 @@ tested-with: GHC == 6.12.1 bug-reports: http://github.com/pepeiborra/control-monad-exception/issues +extra-source-files:+  changelog+ Flag extensibleExceptions   description: Use extensible-exception package   default: False@@ -92,7 +80,10 @@   buildable: True    build-depends: failure >= 0.1 && < 0.3                , transformers >= 0.2+               , transformers-base >= 0.4.1                , monadloc >= 0.7+               , monad-control >= 0.3+               , lifted-base >= 0.2.1    if flag(extensibleExceptions)     build-depends:@@ -121,6 +112,8 @@    exposed-modules:      Control.Monad.Exception+     Control.Monad.Exception.Pure+     Control.Monad.Exception.IO      Control.Monad.Exception.Base      Control.Monad.Exception.Catch      Control.Monad.Exception.Throws