2 {-# OPTIONS_GHC -XNoImplicitPrelude #-}
3 {-# OPTIONS_HADDOCK hide #-}
4 -----------------------------------------------------------------------------
6 -- Module : GHC.Exception
7 -- Copyright : (c) The University of Glasgow, 1998-2002
8 -- License : see libraries/base/LICENSE
10 -- Maintainer : cvs-ghc@haskell.org
11 -- Stability : internal
12 -- Portability : non-portable (GHC extensions)
14 -- Exceptions and exception-handling functions.
16 -----------------------------------------------------------------------------
19 module GHC.Exception where
22 import {-# SOURCE #-} Data.Typeable (Typeable, cast)
27 %*********************************************************
29 \subsection{Exceptions}
31 %*********************************************************
35 The @SomeException@ type is the root of the exception type hierarchy.
36 When an exception of type @e@ is thrown, behind the scenes it is
37 encapsulated in a @SomeException@.
39 data SomeException = forall e . Exception e => SomeException e
42 instance Show SomeException where
43 showsPrec p (SomeException e) = showsPrec p e
46 Any type that you wish to throw or catch as an exception must be an
47 instance of the @Exception@ class. The simplest case is a new exception
48 type directly below the root:
50 > data MyException = ThisException | ThatException
51 > deriving (Show, Typeable)
53 > instance Exception MyException
55 The default method definitions in the @Exception@ class do what we need
56 in this case. You can now throw and catch @ThisException@ and
57 @ThatException@ as exceptions:
60 *Main> throw ThisException `catch` \e -> putStrLn (\"Caught \" ++ show (e :: MyException))
64 In more complicated examples, you may wish to define a whole hierarchy
67 > ---------------------------------------------------------------------
68 > -- Make the root exception type for all the exceptions in a compiler
70 > data SomeCompilerException = forall e . Exception e => SomeCompilerException e
73 > instance Show SomeCompilerException where
74 > show (SomeCompilerException e) = show e
76 > instance Exception SomeCompilerException
78 > compilerExceptionToException :: Exception e => e -> SomeException
79 > compilerExceptionToException = toException . SomeCompilerException
81 > compilerExceptionFromException :: Exception e => SomeException -> Maybe e
82 > compilerExceptionFromException x = do
83 > SomeCompilerException a <- fromException x
86 > ---------------------------------------------------------------------
87 > -- Make a subhierarchy for exceptions in the frontend of the compiler
89 > data SomeFrontendException = forall e . Exception e => SomeFrontendException e
92 > instance Show SomeFrontendException where
93 > show (SomeFrontendException e) = show e
95 > instance Exception SomeFrontendException where
96 > toException = compilerExceptionToException
97 > fromException = compilerExceptionFromException
99 > frontendExceptionToException :: Exception e => e -> SomeException
100 > frontendExceptionToException = toException . SomeFrontendException
102 > frontendExceptionFromException :: Exception e => SomeException -> Maybe e
103 > frontendExceptionFromException x = do
104 > SomeFrontendException a <- fromException x
107 > ---------------------------------------------------------------------
108 > -- Make an exception type for a particular frontend compiler exception
110 > data MismatchedParentheses = MismatchedParentheses
111 > deriving (Typeable, Show)
113 > instance Exception MismatchedParentheses where
114 > toException = frontendExceptionToException
115 > fromException = frontendExceptionFromException
117 We can now catch a @MismatchedParentheses@ exception as
118 @MismatchedParentheses@, @SomeFrontendException@ or
119 @SomeCompilerException@, but not other types, e.g. @IOException@:
122 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: MismatchedParentheses))
123 Caught MismatchedParentheses
124 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeFrontendException))
125 Caught MismatchedParentheses
126 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeCompilerException))
127 Caught MismatchedParentheses
128 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: IOException))
129 *** Exception: MismatchedParentheses
133 class (Typeable e, Show e) => Exception e where
134 toException :: e -> SomeException
135 fromException :: SomeException -> Maybe e
137 toException = SomeException
138 fromException (SomeException e) = cast e
140 instance Exception SomeException where
145 %*********************************************************
147 \subsection{Primitive throw}
149 %*********************************************************
152 -- | Throw an exception. Exceptions may be thrown from purely
153 -- functional code, but may only be caught within the 'IO' monad.
154 throw :: Exception e => e -> a
155 throw e = raise# (toException e)
159 -- |This is thrown when the user calls 'error'. The @String@ is the
160 -- argument given to 'error'.
161 data ErrorCall = ErrorCall String
164 instance Exception ErrorCall
166 instance Show ErrorCall where
167 showsPrec _ (ErrorCall err) = showString err
171 -- |Arithmetic exceptions.
178 deriving (Eq, Ord, Typeable)
180 instance Exception ArithException
182 instance Show ArithException where
183 showsPrec _ Overflow = showString "arithmetic overflow"
184 showsPrec _ Underflow = showString "arithmetic underflow"
185 showsPrec _ LossOfPrecision = showString "loss of precision"
186 showsPrec _ DivideByZero = showString "divide by zero"
187 showsPrec _ Denormal = showString "denormal"