1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
module Main where
import qualified Control.Exception as Exception
import System.IO.Error (mkIOError, catchIOError)
import Data.IORef
safeCatch :: IO () -> IO ()
safeCatch f = Exception.catch f
((\_ -> return ()) :: Exception.SomeException -> IO ())
type Thrower = IO Bool
type Catcher = IO Bool -> IO () -> IO ()
checkCatch :: Catcher -> Thrower -> IO Bool
checkCatch catcher thrower = do
ref <- newIORef False
safeCatch (catcher thrower (writeIORef ref True))
readIORef ref
data Named a = MkNamed String a
checkNamedCatch :: Named Catcher -> Named Thrower -> IO ()
checkNamedCatch (MkNamed cname catcher) (MkNamed tname thrower) = do
didCatch <- checkCatch catcher thrower
putStrLn (cname ++ (if didCatch then " CAUGHT " else " MISSED ") ++ tname)
checkNamedCatches :: [Named Catcher] -> [Named Thrower] -> IO ()
checkNamedCatches [] _ = return ()
checkNamedCatches _ [] = return ()
checkNamedCatches [c] (t:tr) = do checkNamedCatch c t
checkNamedCatches [c] tr
checkNamedCatches (c:cr) ts = do checkNamedCatches [c] ts
checkNamedCatches cr ts
-- throwers
returnThrower :: Named Thrower
returnThrower = MkNamed "return" (return True)
returnUndefinedThrower :: Named Thrower
returnUndefinedThrower = MkNamed "return undefined" (return undefined)
returnErrorThrower :: Named Thrower
returnErrorThrower = MkNamed "return error" (return (error "some error"))
undefinedThrower :: Named Thrower
undefinedThrower = MkNamed "undefined" undefined
failThrower :: Named Thrower
failThrower = MkNamed "fail" (fail "some failure")
errorThrower :: Named Thrower
errorThrower = MkNamed "error" (error "some error")
throwThrower :: Named Thrower
throwThrower = MkNamed "Exception.throw"
(Exception.throw (Exception.ErrorCall "throw error"))
ioErrorErrorCallThrower :: Named Thrower
ioErrorErrorCallThrower = MkNamed "ioError ErrorCall"
(Exception.throwIO (Exception.ErrorCall "throw error"))
ioErrorIOExceptionThrower :: Named Thrower
ioErrorIOExceptionThrower = MkNamed "ioError IOException"
(Exception.throwIO (mkIOError undefined undefined undefined undefined))
returnThrowThrower :: Named Thrower
returnThrowThrower = MkNamed "return Exception.throw"
(return (Exception.throw (Exception.ErrorCall "throw error")))
-- catchers
bindCatcher :: Named Catcher
bindCatcher = MkNamed ">>" (>>)
preludeCatchCatcher :: Named Catcher
preludeCatchCatcher = MkNamed "Prelude.catch"
(\f cc -> catchIOError (f >> (return ())) (const cc))
ceCatchCatcher :: Named Catcher
ceCatchCatcher = MkNamed "Exception.catch"
(\f cc -> Exception.catch (f >> (return ())) (const cc :: Exception.SomeException -> IO ()))
finallyCatcher :: Named Catcher
finallyCatcher = MkNamed "Exception.finally"
(\f cc -> Exception.finally (f >> (return ())) cc)
main = checkNamedCatches
[bindCatcher,preludeCatchCatcher,ceCatchCatcher,finallyCatcher]
[returnThrower,returnUndefinedThrower,returnThrowThrower,returnErrorThrower,failThrower,
errorThrower,throwThrower,ioErrorErrorCallThrower,ioErrorIOExceptionThrower,undefinedThrower]
|