-
Notifications
You must be signed in to change notification settings - Fork 1
/
ch30.hs
84 lines (62 loc) · 1.96 KB
/
ch30.hs
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
module Ch30 where
import Control.Exception
import Control.Monad
import Control.Concurrent (forkIO, threadDelay)
import System.IO
data MyException =
MyException1 Int
| MyException2
deriving (Eq, Show)
instance Exception MyException
toException' :: Exception e => IO (Either e a) -> IO (Either SomeException a)
toException' ioa = do
result <- ioa
case result of
Left e -> return $ Left $ toException e
Right ok -> return $ Right ok
catchArith' :: IO a -> IO (Either SomeException a)
catchArith' =
let tryS :: IO a -> IO (Either ArithException a)
tryS = try
in toException' . tryS
catchAsync' :: IO a -> IO (Either SomeException a)
catchAsync' =
let tryS :: IO a -> IO (Either AsyncException a)
tryS = try
in toException' . tryS
canICatch' :: Exception e => e -> IO (Either SomeException ())
canICatch' e = fmap (join . join) $ (catchAsync' . catchArith' . catchAsync') (throwIO e)
canICatchAll :: Exception e => e -> IO (Either SomeException ())
canICatchAll e = try $ throwIO e
catchArith :: ArithException -> Maybe SomeException
catchArith err = Just $ toException err
catchAsync :: AsyncException -> Maybe SomeException
catchAsync err = Just $ toException err
catchMy :: MyException -> Maybe SomeException
catchMy err = Just $ toException err
canICatch :: Exception e => e -> IO (Either SomeException ())
canICatch e = join <$> (tryJust catchMy $ tryJust catchArith $ throwIO e)
catchTest :: IO ()
catchTest = do
canICatch DivideByZero >>= print
canICatch (MyException1 1337) >>= print
canICatch StackOverflow >>= print
canICatch MyException2 >>= print
openAndWrite :: IO ()
openAndWrite = do
print "0"
h <- openFile "test.dat" WriteMode
print "1"
hPutStr h (replicate 10000000 '0' ++ "abc")
print "2"
hClose h
print "done"
data PleaseDie =
PleaseDie
deriving Show
instance Exception PleaseDie
main :: IO ()
main = do
threadId <- forkIO $ mask_ openAndWrite
threadDelay 200
throwTo threadId PleaseDie