87d85d8e63a445dab8109914d0619465000ac9a3
[ghc.git] / libraries / base / GHC / Exception.lhs
1 \begin{code}
2 {-# LANGUAGE Trustworthy #-}
3 {-# LANGUAGE NoImplicitPrelude
4            , ExistentialQuantification
5            , MagicHash
6            , DeriveDataTypeable
7   #-}
8 {-# OPTIONS_HADDOCK hide #-}
9 -----------------------------------------------------------------------------
10 -- |
11 -- Module      :  GHC.Exception
12 -- Copyright   :  (c) The University of Glasgow, 1998-2002
13 -- License     :  see libraries/base/LICENSE
14 -- 
15 -- Maintainer  :  cvs-ghc@haskell.org
16 -- Stability   :  internal
17 -- Portability :  non-portable (GHC extensions)
18 --
19 -- Exceptions and exception-handling functions.
20 -- 
21 -----------------------------------------------------------------------------
22
23 -- #hide
24 module GHC.Exception where
25
26 import Data.Maybe
27 import {-# SOURCE #-} Data.Typeable (Typeable, cast)
28 import GHC.Base
29 import GHC.Show
30 \end{code}
31
32 %*********************************************************
33 %*                                                      *
34 \subsection{Exceptions}
35 %*                                                      *
36 %*********************************************************
37
38 \begin{code}
39 {- |
40 The @SomeException@ type is the root of the exception type hierarchy.
41 When an exception of type @e@ is thrown, behind the scenes it is
42 encapsulated in a @SomeException@.
43 -}
44 data SomeException = forall e . Exception e => SomeException e
45     deriving Typeable
46
47 instance Show SomeException where
48     showsPrec p (SomeException e) = showsPrec p e
49
50 {- |
51 Any type that you wish to throw or catch as an exception must be an
52 instance of the @Exception@ class. The simplest case is a new exception
53 type directly below the root:
54
55 > data MyException = ThisException | ThatException
56 >     deriving (Show, Typeable)
57 >
58 > instance Exception MyException
59
60 The default method definitions in the @Exception@ class do what we need
61 in this case. You can now throw and catch @ThisException@ and
62 @ThatException@ as exceptions:
63
64 @
65 *Main> throw ThisException \`catch\` \\e -> putStrLn (\"Caught \" ++ show (e :: MyException))
66 Caught ThisException
67 @
68
69 In more complicated examples, you may wish to define a whole hierarchy
70 of exceptions:
71
72 > ---------------------------------------------------------------------
73 > -- Make the root exception type for all the exceptions in a compiler
74 >
75 > data SomeCompilerException = forall e . Exception e => SomeCompilerException e
76 >     deriving Typeable
77 >
78 > instance Show SomeCompilerException where
79 >     show (SomeCompilerException e) = show e
80 >
81 > instance Exception SomeCompilerException
82 >
83 > compilerExceptionToException :: Exception e => e -> SomeException
84 > compilerExceptionToException = toException . SomeCompilerException
85 >
86 > compilerExceptionFromException :: Exception e => SomeException -> Maybe e
87 > compilerExceptionFromException x = do
88 >     SomeCompilerException a <- fromException x
89 >     cast a
90 >
91 > ---------------------------------------------------------------------
92 > -- Make a subhierarchy for exceptions in the frontend of the compiler
93 >
94 > data SomeFrontendException = forall e . Exception e => SomeFrontendException e
95 >     deriving Typeable
96 >
97 > instance Show SomeFrontendException where
98 >     show (SomeFrontendException e) = show e
99 >
100 > instance Exception SomeFrontendException where
101 >     toException = compilerExceptionToException
102 >     fromException = compilerExceptionFromException
103 >
104 > frontendExceptionToException :: Exception e => e -> SomeException
105 > frontendExceptionToException = toException . SomeFrontendException
106 >
107 > frontendExceptionFromException :: Exception e => SomeException -> Maybe e
108 > frontendExceptionFromException x = do
109 >     SomeFrontendException a <- fromException x
110 >     cast a
111 >
112 > ---------------------------------------------------------------------
113 > -- Make an exception type for a particular frontend compiler exception
114 >
115 > data MismatchedParentheses = MismatchedParentheses
116 >     deriving (Typeable, Show)
117 >
118 > instance Exception MismatchedParentheses where
119 >     toException   = frontendExceptionToException
120 >     fromException = frontendExceptionFromException
121
122 We can now catch a @MismatchedParentheses@ exception as
123 @MismatchedParentheses@, @SomeFrontendException@ or
124 @SomeCompilerException@, but not other types, e.g. @IOException@:
125
126 @
127 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: MismatchedParentheses))
128 Caught MismatchedParentheses
129 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeFrontendException))
130 Caught MismatchedParentheses
131 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: SomeCompilerException))
132 Caught MismatchedParentheses
133 *Main> throw MismatchedParentheses `catch` \e -> putStrLn (\"Caught \" ++ show (e :: IOException))
134 *** Exception: MismatchedParentheses
135 @
136
137 -}
138 class (Typeable e, Show e) => Exception e where
139     toException   :: e -> SomeException
140     fromException :: SomeException -> Maybe e
141
142     toException = SomeException
143     fromException (SomeException e) = cast e
144
145 instance Exception SomeException where
146     toException se = se
147     fromException = Just
148 \end{code}
149
150 %*********************************************************
151 %*                                                      *
152 \subsection{Primitive throw}
153 %*                                                      *
154 %*********************************************************
155
156 \begin{code}
157 -- | Throw an exception.  Exceptions may be thrown from purely
158 -- functional code, but may only be caught within the 'IO' monad.
159 throw :: Exception e => e -> a
160 throw e = raise# (toException e)
161 \end{code}
162
163 \begin{code}
164 -- |This is thrown when the user calls 'error'. The @String@ is the
165 -- argument given to 'error'.
166 data ErrorCall = ErrorCall String
167     deriving Typeable
168
169 instance Exception ErrorCall
170
171 instance Show ErrorCall where
172     showsPrec _ (ErrorCall err) = showString err
173
174 -----
175
176 -- |Arithmetic exceptions.
177 data ArithException
178   = Overflow
179   | Underflow
180   | LossOfPrecision
181   | DivideByZero
182   | Denormal
183   deriving (Eq, Ord, Typeable)
184
185 instance Exception ArithException
186
187 instance Show ArithException where
188   showsPrec _ Overflow        = showString "arithmetic overflow"
189   showsPrec _ Underflow       = showString "arithmetic underflow"
190   showsPrec _ LossOfPrecision = showString "loss of precision"
191   showsPrec _ DivideByZero    = showString "divide by zero"
192   showsPrec _ Denormal        = showString "denormal"
193
194 \end{code}