forked from sebfisch/explicit-sharing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTest.hs
190 lines (145 loc) · 5.3 KB
/
Test.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
{-# LANGUAGE
NoMonomorphismRestriction,
MultiParamTypeClasses,
OverlappingInstances,
IncoherentInstances,
FlexibleInstances,
FlexibleContexts,
RankNTypes
#-}
import Control.Monad.Sharing
import Data.Monadic.List
main = do
putStr "failing tests: "
print . map fst . filter (not . snd) . zip [1..] $ tests
where
tests = [ dup_coin_let, dup_coin_bind, dup_coin_share
, lazy_share, heads_bind, heads_share, dup_first_coin
, one_coin, two_coins, dup_coin, dupnot_coin
, first_rep, rep_coin
, dup_list, ignore_shared, empty_rep
, nest_lazy, nest_share1, nest_share2
, dup_dup, dup_two_coins, dup_head, dup_head_lazy
]
instance Monad m => Shareable m (Int,Int)
where
shareArgs _ = return
instance Monad m => Shareable m ([Int],[Int])
where
shareArgs _ = return
instance Monad m => Shareable m ((Int,Int),(Int,Int))
where
shareArgs _ = return
instance Monad m => Convertible m (Int,Int) (Int,Int)
where
convert = return
instance (Monad m, Shareable m a) => Shareable m (m a, m a)
where
shareArgs f (x,y) = return (,) `ap` f x `ap` f y
instance (Monad m, Convertible m a b) => Convertible m (m a, m a) (b, b)
where
convert (x,y) = return (,) `ap` (x >>= convert) `ap` (y >>= convert)
-- assertEqual :: (Shareable (Lazy []) a, Convertible (Lazy []) a b, Eq b)
-- => [b] -> Lazy [] a -> Bool
assertEqual :: Eq a => [a] -> (forall s . Sharing s => s a) -> Bool
assertEqual res test = zipEq (unsafeResults test) res
where
zipEq [] [] = True
zipEq [] _ = False
zipEq (_:_) [] = True
zipEq (x:xs) (y:ys) = (x==y) && zipEq xs ys
coin :: MonadPlus m => m Int
coin = return 0 `mplus` return 1
-- examples from paper
duplicate :: Monad m => m a -> m (a,a)
duplicate a = do x <- a; y <- a; return (x,y)
dup_coin_let = assertEqual [(0,0)::(Int,Int),(0,1),(1,0),(1,1)] $
let x = coin in duplicate x
dup_coin_bind = assertEqual [(0,0)::(Int,Int),(1,1)] $ do
x <- coin
duplicate (return x)
dup_coin_share = assertEqual [(0,0)::(Int,Int),(1,1)] $ do
x <- share coin
duplicate x
-- strict_bind = -- diverges intentionally
-- do x <- undefined :: Lazy [] Int
-- duplicate (const (return 2) (return x))
lazy_share = assertEqual [(2::Int,2::Int)] $
do x <- share undef
duplicate (const (return (2::Int)) x)
undef :: Monad m => m Int
undef = undefined
dupl :: Monad m => m a -> m (List m a)
dupl x = cons x (cons x nil)
heads_bind = assertEqual [[0,0::Int],[0,1],[1,0],[1,1]] $ do
x <- cons coin undefined
dupl (first (return x)) >>= convert
heads_share = assertEqual [[0,0::Int],[1,1]] $ do
x <- share (cons coin undefined)
dupl (first x) >>= convert
coins :: MonadPlus m => m (List m Int)
coins = nil `mplus` cons coin coins
dup_first_coin = assertEqual [[0::Int,0],[1,1]] $ do
cs <- share coins
dupl (first cs) >>= convert
-- other examples
one_coin = assertEqual [0,1::Int] coin
two_coins = assertEqual [(0,0),(0::Int,1::Int),(1,0),(1,1)] $
return (coin, coin) >>= convertPair
where
convertPair (a,b) = do x <- a; y <- b; return (x,y)
dup_coin = assertEqual [(0::Int,0::Int),(1,1)] $ dup coin >>= convert
dup :: (Monad m, Sharing m, Shareable m a) => m a -> m (m a, m a)
dup a = do
x <- share a
return (x,x)
dupnot_coin = assertEqual [(1::Int,1::Int),(0,0)] $ dupnot coin >>= convert
dupnot a = do
x <- share a
return (liftM ((-)1) x, liftM ((-)1) x)
first_rep = assertEqual [42::Int] $
first (first (rep (rep (return (42::Int)))))
rep a = do
x <- share a
cons x (rep x)
rep_coin = assertEqual [(0::Int,0::Int),(1,1)] $ do
Cons x xs <- rep coin
convert (x, first xs)
dup_list = assertEqual [([],[])
,([0::Int],[0::Int])
,([0,0],[0,0])
,([0,0,0],[0,0,0])] $
dup coins >>= convert
ignore_shared = assertEqual [(0::Int,1::Int)] $ ign_pair mzero >>= convertPair
where
convertPair (a,b) = do x <- a; y <- b; return (x,y)
ign_pair :: Sharing m => m Int -> m (m Int, m Int)
ign_pair a = do
x <- share a
return (const (return 0) x, const (return 1) x)
empty_rep = assertEqual [False] $ isEmpty (rep undef)
nest_lazy = assertEqual [42::Int] $ do
x <- share (cons (return 42) mzero)
first x
nest_share1 = assertEqual [(0::Int,0::Int),(1,1)] $ do
x <- share (share (return True) >> coin)
convert (x,x)
nest_share2 = assertEqual [(0::Int,0::Int),(1,1)] $ do
x <- share (share coin >>= id)
convert (x,x)
dup_dup = assertEqual [((0::Int,0::Int),(0::Int,0::Int)),((1,1),(1,1))] $
(dup (dup coin)) >>= convert
dup_two_coins = assertEqual [((0::Int,0::Int),(0::Int,0::Int)),((0,1),(0,1))
,((1,0),(1,0)),((1,1),(1,1))] $ do
x <- share coin
y <- share coin
convertPair (return (x,y),return (x,y))
where
convertPair (a,b) = do x <- a >>= convert; y <- b >>= convert; return (x,y)
dup_head = assertEqual [(0::Int,0::Int),(1,1)] $
heads (cons coin nil) >>= convert
heads l = do
xs <- share l
return (first xs, first xs)
dup_head_lazy = assertEqual [(0::Int,0::Int),(1,1)] $
heads (cons coin undefined) >>= convert