Contents Important trivia Hierarchies of Exceptions Unchecked exceptions Unchecked exceptions Stack Traces Understanding GHC errors The EM monad The EMT monad transformer The Throws type class Exception primitives Reexports
Description

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
```
Synopsis
type EM l = EMT l Identity
tryEM :: EM (AnyException l) a -> Either SomeException a
runEM :: EM NoExceptions a -> a
runEMParanoid :: EM ParanoidMode a -> a
newtype EMT l m a = EMT {
 unEMT :: m (Either (CallTrace, CheckedException l) a)
}
type CallTrace = [String]
tryEMT :: Monad m => EMT (AnyException l) m a -> m (Either SomeException a)
runEMT :: Monad m => EMT NoExceptions m a -> m a
runEMTParanoid :: Monad m => EMT ParanoidMode m a -> m a
type AnyException = Caught SomeException
class Exception e => UncaughtException e
class Exception e => Throws e l
data Caught e l
throw :: (Exception e, Throws e l, Monad m) => e -> EMT l m a
rethrow :: (Throws e l, Monad m) => CallTrace -> e -> EMT l m a
catch :: (Exception e, Monad m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a
catchWithSrcLoc :: (Exception e, Monad m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a
finally :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
onException :: Monad m => EMT l m a -> EMT l m b -> EMT l m a
bracket :: Monad m => EMT l m a -> (a -> EMT l m b) -> (a -> EMT l m c) -> EMT l m c
wrapException :: (Exception e, Throws e' l, Monad m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a
showExceptionWithTrace :: Exception e => [String] -> e -> String
data FailException = FailException String
mplusDefault :: Monad m => EMT l m a -> EMT l m a -> EMT l m a
class (Typeable e, Show e) => Exception e where
 toException :: e -> SomeException fromException :: SomeException -> Maybe e
data SomeException where
 SomeException :: Exception e => e -> SomeException
class Typeable a where
 typeOf :: a -> TypeRep
class Try f where
 type Error f :: * try :: ApplicativeFailure (Error f) f' => f a -> f' a
data NothingException = NothingException
class Failure e f where
 failure :: e -> f v
class (Monad f, Applicative f, Failure e f) => MonadFailure e f
class Failure e f => WrapFailure e f where
 wrapFailure :: (forall eIn. Exception eIn => eIn -> e) -> f a -> f a
 withLoc :: String -> m a -> m a
withLocTH :: Q Exp
Important trivia
Hierarchies of Exceptions

If your sets of exceptions are hierarchical then you need to teach Throws about the hierarchy.

```                                                            --   TopException
--         |
instance Throws MidException   (Caught TopException l)   --         |
--   MidException
instance Throws ChildException (Caught MidException l)   --         |
instance Throws ChildException (Caught TopException l)   --         |
--  ChildException
```
Unchecked exceptions
Unchecked exceptions

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.

Stack Traces

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)
```
Understanding GHC 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)
instance (Exception e) => Throws e (Caught e l)
(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.

 type EM l = EMT l Identity Source
A monad of explicitly typed, checked exceptions
 tryEM :: EM (AnyException l) a -> Either SomeException a Source
Run a computation explicitly handling exceptions
 runEM :: EM NoExceptions a -> a Source
Run a safe computation
 runEMParanoid :: EM ParanoidMode a -> a Source
Run a computation checking even unchecked (UncaughtExceptions) exceptions
 newtype EMT l m a Source
A Monad Transformer for explicitly typed checked exceptions.
Constructors
EMT
 unEMT :: m (Either (CallTrace, CheckedException l) a)
Instances
 type CallTrace = [String] Source
 tryEMT :: Monad m => EMT (AnyException l) m a -> m (Either SomeException a) Source
Run a computation explicitly handling exceptions
 runEMT :: Monad m => EMT NoExceptions m a -> m a Source
Run a safe computation
 runEMTParanoid :: Monad m => EMT ParanoidMode m a -> m a Source
Run a safe computation checking even unchecked (UncaughtException) exceptions
 type AnyException = Caught SomeException Source
 class Exception e => UncaughtException e Source

Uncaught Exceptions model unchecked exceptions

In order to declare an unchecked exception E, all that is needed is to make e an instance of UncaughtException

``` instance UncaughtException E
```

Note that declaring an exception E as unchecked does not automatically turn its children as unchecked too. This is a shortcoming of the current encoding.

If that is what you want, then declare E as unchecked and unexplicit using an instance of Throws:

``` instance Throws E l
```
Instances
 UncaughtException SomeException
The Throws type class
 class Exception e => Throws e l Source

Throws is a type level binary relationship used to model a list of exceptions.

There is only one case in which the user must add further instances to Throws, and that is to encode the hierarchy of exceptions.

Subtyping
As there is no way to automatically infer the subcases of an exception, they have to be encoded manually mirroring the hierarchy defined in the defined Exception instances. For example, the following instance encodes that MyFileNotFoundException is a subexception of MyIOException :
``` instance Throws MyFileNotFoundException (Caught MyIOException l)
```

Throws is not a transitive relation and every ancestor relation must be explicitly encoded.

```                                                            --   TopException
--         |
instance Throws MidException   (Caught TopException l)   --         |
--   MidException
instance Throws ChildException (Caught MidException l)   --         |
instance Throws ChildException (Caught TopException l)   --         |
--  ChildException
```

SomeException is automatically an ancestor of every other exception type.

Instances
 UncaughtException e => Throws e NoExceptions Exception e => Throws e (Caught SomeException l) Exception e => Throws e (Caught e l) Throws e l => Throws e (Caught e' l) Throws SomeException (Caught SomeException l)
 data Caught e l Source
A type level witness of a exception handler.
Instances
 Exception e => Throws e (Caught SomeException l) Exception e => Throws e (Caught e l) Throws e l => Throws e (Caught e' l) Throws SomeException (Caught SomeException l) (Exception e, Monad m) => MonadCatch e (EMT (Caught e l) m) (EMT l m)
Exception primitives
 throw :: (Exception e, Throws e l, Monad m) => e -> EMT l m a Source
The throw primitive
 rethrow :: (Throws e l, Monad m) => CallTrace -> e -> EMT l m a Source
Rethrow an exception keeping the call trace
 catch :: (Exception e, Monad m) => EMT (Caught e l) m a -> (e -> EMT l m a) -> EMT l m a Source
The catch primitive
 catchWithSrcLoc :: (Exception e, Monad m) => EMT (Caught e l) m a -> (CallTrace -> e -> EMT l m a) -> EMT l m a Source
Like catch but makes the call trace available
 finally :: Monad m => EMT l m a -> EMT l m b -> EMT l m a Source
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.
 onException :: Monad m => EMT l m a -> EMT l m b -> EMT l m a Source
Like finally, but performs the second computation only when the first one rises an exception
 bracket Source
 :: Monad m => EMT l m a release resource -> a -> EMT l m b computation -> a -> EMT l m c -> EMT l m c
 wrapException :: (Exception e, Throws e' l, Monad m) => (e -> e') -> EMT (Caught e l) m a -> EMT l m a Source
Capture an exception e, wrap it, and rethrow. Keeps the original monadic call trace.
 showExceptionWithTrace :: Exception e => [String] -> e -> String Source
 data FailException Source
FailException is thrown by Monad fail
Constructors
 FailException String
Instances
 Show FailException Typeable FailException Exception FailException
Constructors
Instances
 mplusDefault :: Monad m => EMT l m a -> EMT l m a -> EMT l m a Source
This function may be used as a value for mplus in MonadPlus
Reexports
 class (Typeable e, Show e) => Exception e where Source

Any type that you wish to throw or catch as an exception must be an instance of the Exception class. The simplest case is a new exception type directly below the root:

data MyException = ThisException | ThatException deriving (Show, Typeable) instance Exception MyException

The default method definitions in the Exception class do what we need in this case. You can now throw and catch ThisException and ThatException as exceptions:

*Main> throw ThisException catch e -> putStrLn ("Caught " ++ show (e :: MyException)) Caught ThisException

In more complicated examples, you may wish to define a whole hierarchy of exceptions:

--------------------------------------------------------------------- -- Make the root exception type for all the exceptions in a compiler data SomeCompilerException = forall e . Exception e => SomeCompilerException e deriving Typeable instance Show SomeCompilerException where show (SomeCompilerException e) = show e instance Exception SomeCompilerException compilerExceptionToException :: Exception e => e -> SomeException compilerExceptionToException = toException . SomeCompilerException compilerExceptionFromException :: Exception e => SomeException -> Maybe e compilerExceptionFromException x = do SomeCompilerException a <- fromException x cast a --------------------------------------------------------------------- -- Make a subhierarchy for exceptions in the frontend of the compiler data SomeFrontendException = forall e . Exception e => SomeFrontendException e deriving Typeable instance Show SomeFrontendException where show (SomeFrontendException e) = show e instance Exception SomeFrontendException where toException = compilerExceptionToException fromException = compilerExceptionFromException frontendExceptionToException :: Exception e => e -> SomeException frontendExceptionToException = toException . SomeFrontendException frontendExceptionFromException :: Exception e => SomeException -> Maybe e frontendExceptionFromException x = do SomeFrontendException a <- fromException x cast a --------------------------------------------------------------------- -- Make an exception type for a particular frontend compiler exception data MismatchedParentheses = MismatchedParentheses deriving (Typeable, Show) instance Exception MismatchedParentheses where toException = frontendExceptionToException fromException = frontendExceptionFromException

We can now catch a MismatchedParentheses exception as MismatchedParentheses, SomeFrontendException or SomeCompilerException, but not other types, e.g. IOException:

*Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses)) Caught MismatchedParentheses *Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException)) Caught MismatchedParentheses *Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException)) Caught MismatchedParentheses *Main> throw MismatchedParentheses catch e -> putStrLn ("Caught " ++ show (e :: IOException)) *** Exception: MismatchedParentheses
Methods
 toException :: e -> SomeException Source
 fromException :: SomeException -> Maybe e Source
Instances
 Exception PatternMatchFail Exception RecSelError Exception RecConError Exception RecUpdError Exception NoMethodError Exception NonTermination Exception NestedAtomically Exception SomeException Exception ErrorCall Exception ArithException Exception StringException Exception NothingException Exception NullException Exception MonadZeroException Exception FailException
 data SomeException where Source
The SomeException type is the root of the exception type hierarchy. When an exception of type e is thrown, behind the scenes it is encapsulated in a SomeException.
Constructors
 SomeException :: Exception e => e -> SomeException
Instances
 Show SomeException Typeable SomeException Exception SomeException UncaughtException SomeException Exception e => Throws e (Caught SomeException l) Throws SomeException (Caught SomeException l)
 class Typeable a where Source
The class Typeable allows a concrete representation of a type to be calculated.
Methods
 typeOf :: a -> TypeRep Source
Takes a value of type a and returns a concrete representation of that type. The value of the argument should be ignored by any instance of Typeable, so that it is safe to pass undefined as the argument.
Instances
 Typeable Bool Typeable Char Typeable Double Typeable Float Typeable Int Typeable Int8 Typeable Int16 Typeable Int32 Typeable Int64 Typeable Integer Typeable Ordering Typeable RealWorld Typeable Word Typeable Word8 Typeable Word16 Typeable Word32 Typeable Word64 Typeable () Typeable PatternMatchFail Typeable RecSelError Typeable RecConError Typeable RecUpdError Typeable NoMethodError Typeable NonTermination Typeable NestedAtomically Typeable SomeException Typeable ErrorCall Typeable ArithException Typeable TypeRep Typeable TyCon Typeable StringException Typeable NothingException Typeable NullException Typeable MonadZeroException Typeable FailException (Typeable1 s, Typeable a) => Typeable (s a)
 class Try f where Source
Associated Types
 type Error f :: * Source
Methods
 try :: ApplicativeFailure (Error f) f' => f a -> f' a Source
Instances
 Try [] Try Maybe Try (Either e)
 data NothingException Source
Constructors
 NothingException
Instances
 Show NothingException Typeable NothingException Exception NothingException
 class Failure e f where Source
Methods
 failure :: e -> f v Source
Instances
 Failure e [] Failure e Maybe Exception e => Failure e IO Failure e (Either e) (Exception e, Throws e l, Monad m) => Failure e (EMT l m)
 class (Monad f, Applicative f, Failure e f) => MonadFailure e f Source
Instances
 class Failure e f => WrapFailure e f where Source
Methods
 wrapFailure :: (forall eIn. Exception eIn => eIn -> e) -> f a -> f a Source
Wrap the failure value, if any, with the given function. This is useful in particular when you want all the exceptions returned from a certain library to be of a certain type, even if they were generated by a different library.
Instances
 Exception e => WrapFailure e IO (Exception e, Throws e l, Failure e m, Monad m) => WrapFailure e (EMT l m)
Generating stack traces for failures
Methods
 withLoc :: String -> m a -> m a Source
withLoc records the given source location in the failure trace if the underlying monad supports recording location traces
Instances