This repository was archived by the owner on Apr 20, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path3_2_5_callCFC.hs
More file actions
96 lines (79 loc) · 2.29 KB
/
3_2_5_callCFC.hs
File metadata and controls
96 lines (79 loc) · 2.29 KB
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
96
{-
*Main> evalFailCont $ addInts "15" "12"
Right 27
*Main> evalFailCont $ addInts "15" "122"
Right 42
*Main> runFailCont (addInts "15" "") print (putStrLn . ("Oops: " ++) . show)
Oops: EmptyInput
-}
{-# LANGUAGE DeriveFunctor #-}
import Control.Monad.Trans.Except
import Control.Monad.Trans.Cont
import Control.Monad(ap, when)
import Control.Applicative(liftA)
newtype FailCont r e a = FailCont { runFailCont :: (a -> r) -> (e -> r) -> r }
-- deriving Functor
instance Functor (FailCont r e) where
fmap = liftA
instance Applicative (FailCont r e) where
pure = return
(<*>) = ap
instance Monad (FailCont r e) where
return x = FailCont $ \c _ -> c x
FailCont f >>= g =
FailCont $ \h -> \k ->
f (\a -> runFailCont (g a) h k) k
toFailCont :: Except e a -> FailCont r e a
toFailCont e = FailCont $ \f -> \g ->
case (runExcept e) of
Right x -> f x
Left x -> g x
evalFailCont :: FailCont (Either e a) e a -> Either e a
evalFailCont (FailCont f) = f Right Left
callCC' :: (
(a -> (b -> r) -> r)
-> (a -> r) -> r
)
-> (a -> r)
-> r
callCC' f g = f (\a -> \_ -> g a) g
callCFC :: ((a -> FailCont r e b) -> FailCont r e a)
-> FailCont r e a
callCFC f =
FailCont $
\g ->
\h ->
runFailCont (f (\a -> FailCont $ \_ -> \_ -> g a)) g h
callCFC' :: (
(
a
-> (b -> r)
-> (e -> r)
-> r
)
-> (a -> r)
-> (e -> r)
-> r
)
-> (a -> r)
-> (e -> r)
-> r
callCFC' f = \g -> \h -> f (\a -> \_ -> \_ -> g a) g h
data ReadError = EmptyInput | NoParse String
deriving Show
tryRead :: Read a => String -> Except ReadError a
tryRead "" = throwE EmptyInput
tryRead s = go $ reads s where
go ((r, []):_) = pure r
go _ = throwE $ NoParse s
add :: Int -> Int -> FailCont r e Int
add x y = FailCont $ \ok _ -> ok $ x + y
addInts :: String -> String -> FailCont r ReadError Int
addInts s1 s2 = callCFC $ \k -> do
i1 <- toFailCont $ tryRead s1
i2 <- toFailCont $ tryRead s2
when (i1 + i2 > 100) (k 42)
return $ i1 + i2
ex1 = evalFailCont $ addInts "15" "12"
ex2 = evalFailCont $ addInts "15" "122"
ex3 = runFailCont (addInts "15" "") print (putStrLn . ("Oops: " ++) . show)