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