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