summaryrefslogtreecommitdiff
path: root/prototypes
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-04-08 12:02:33 +0200
committerPéter Diviánszky <divipp@gmail.com>2016-04-08 12:02:33 +0200
commit02c3f915861d53122624417a9d97068d754a4b26 (patch)
treebaeaff1fb4954b5b9a6761772282c8cf268f425a /prototypes
parent2e65df79cda76000ae0b69b8b9b85f4abac7f084 (diff)
split Stream.hs; bugfixes
Diffstat (limited to 'prototypes')
-rw-r--r--prototypes/ShiftReducer.hs361
-rw-r--r--prototypes/Stream.hs248
2 files changed, 366 insertions, 243 deletions
diff --git a/prototypes/ShiftReducer.hs b/prototypes/ShiftReducer.hs
index 97e589a7..f40c7656 100644
--- a/prototypes/ShiftReducer.hs
+++ b/prototypes/ShiftReducer.hs
@@ -16,6 +16,7 @@
16{-# language FlexibleContexts #-} 16{-# language FlexibleContexts #-}
17{-# language TemplateHaskell #-} -- for testing 17{-# language TemplateHaskell #-} -- for testing
18{-# language NoMonomorphismRestriction #-} 18{-# language NoMonomorphismRestriction #-}
19module ShiftReducer where
19 20
20import Data.Monoid 21import Data.Monoid
21import Data.Maybe 22import Data.Maybe
@@ -30,214 +31,7 @@ import Test.QuickCheck.Function
30import GHC.Generics 31import GHC.Generics
31import Debug.Trace 32import Debug.Trace
32 33
33------------------------------------------------------------ utils 34import Stream
34
35iterateN i f x = iterate f x !! i
36
37(<&>) = flip (<$>)
38
39data Void
40
41instance Eq Void where (==) = error "(==) @Void"
42instance Show Void where show = error "show @Void"
43
44{- used later?
45-- supplementary data: data with no semantic relevance
46newtype SData a = SData a
47instance Show (SData a) where show _ = "SData"
48instance Eq (SData a) where _ == _ = True
49instance Ord (SData a) where _ `compare` _ = EQ
50-}
51
52------------------------------------------------------------ streams
53
54-- streams with constant tails
55-- invariant property: Repeat is used when possible (see cons)
56data Stream a
57 = Cons a (Stream a)
58 | Repeat a
59 deriving (Eq, Show, Functor) -- Functor is not proper, may break invariant
60
61-- smart constructor to construct normal form of streams
62cons b (Repeat b') | b == b' = Repeat b'
63cons b x = Cons b x
64
65-- stream head
66sHead (Cons a _) = a
67sHead (Repeat a) = a
68
69-- stream tail
70sTail (Cons _ a) = a
71sTail (Repeat a) = Repeat a
72
73instance Applicative Stream where
74 pure a = Repeat a
75 -- (<*>) is not proper, may break invariant
76 Repeat f <*> Repeat a = Repeat $ f a
77 x <*> y = Cons{-should be cons-} (sHead x $ sHead y) (sTail x <*> sTail y)
78
79foldStream :: (b -> a -> a) -> (b -> a) -> Stream b -> a
80foldStream f g (Cons b u) = f b (foldStream f g u)
81foldStream f g (Repeat b) = g b
82
83-- final value in the stream
84limes :: Stream a -> a
85limes = foldStream const id
86
87-- replace limes by given stream
88sCont :: Eq a => Stream a -> (a -> Stream a) -> Stream a
89sCont as f = foldStream cons f as
90
91-- semantics of Stream
92streamToList :: Stream a -> [a]
93streamToList = foldStream (:) repeat
94
95streamToFun :: Stream a -> Int -> a
96streamToFun u i = streamToList u !! i
97
98sFromList :: Eq a => [a] -> a -> Stream a
99sFromList xs b = foldr cons (Repeat b) xs
100
101instance (Arbitrary a, Eq a) => Arbitrary (Stream a) where
102 arbitrary = sFromList <$> arbitrary <*> arbitrary
103
104-- iterate on stream
105sIterate :: Eq a => (a -> a) -> a -> Stream a
106sIterate f x
107 | y == x = Repeat x
108 | otherwise = Cons x $ sIterate f y
109 where
110 y = f x
111
112sCatMaybes :: Stream (Maybe a) -> [a]
113sCatMaybes = foldStream (\m s -> maybe s (:s) m) (maybe [] repeat)
114
115---------------------------------------------------------- operations involving Boolean streams
116
117mergeStreams :: Eq a => Stream Bool -> Stream a -> Stream a -> Stream a
118mergeStreams (Cons True u) as bs = cons (sHead as) $ mergeStreams u (sTail as) bs
119mergeStreams (Cons False u) as bs = cons (sHead bs) $ mergeStreams u as (sTail bs)
120mergeStreams (Repeat True) as bs = as
121mergeStreams (Repeat False) as bs = bs
122
123sFilter :: Stream Bool -> [a] -> [a]
124sFilter (Cons True u) is = take 1 is ++ sFilter u (drop 1 is)
125sFilter (Cons False u) is = sFilter u (drop 1 is)
126sFilter (Repeat True) is = is
127sFilter (Repeat False) is = []
128
129-- sFilter for streams
130-- the first stream is used when no more element can pass the filter
131filterStream :: Eq a => Stream a -> Stream Bool -> Stream a -> Stream a
132filterStream d (Cons True s) as = cons (sHead as) $ filterStream d s $ sTail as
133filterStream d (Cons False s) as = filterStream d s $ sTail as
134filterStream d (Repeat True) as = as
135filterStream d (Repeat False) as = d
136
137sOr :: Stream Bool -> Stream Bool -> Stream Bool
138sOr (Cons b u) (Cons b' u') = cons (b || b') $ sOr u u'
139sOr (Repeat False) u = u
140sOr (Repeat True) u = Repeat True
141sOr u (Repeat False) = u
142sOr u (Repeat True) = Repeat True
143
144prop_sOr_idemp a = sOr a a == a
145prop_sOr_comm a b = sOr a b == sOr b a
146
147dbAnd a b = not <$> sOr (not <$> a) (not <$> b)
148
149instance Monoid (Stream Bool) where
150 mempty = Repeat False
151 mappend = sOr
152
153prop_StreamBool_monoid_left (a :: Stream Bool) = mempty <> a == a
154prop_StreamBool_monoid_right (a :: Stream Bool) = a <> mempty == a
155prop_StreamBool_monoid_assoc (a :: Stream Bool) b c = (a <> b) <> c == a <> (b <> c)
156
157-- composition of (Stream Bool) values (by sFilter semantics)
158sComp :: Stream Bool -> Stream Bool -> Stream Bool
159sComp bs as = mergeStreams bs as $ Repeat False
160
161prop_sComp a b xs = sFilter (sComp a b) xs == (sFilter b . sFilter a) xs
162prop_sComp_trans a b (getNonNegative -> i) = indexTrans (sComp a b) i == (indexTrans a =<< indexTrans b i)
163
164filterDBUsed :: Stream Bool -> Stream Bool -> Stream Bool
165filterDBUsed = filterStream $ Repeat False
166
167--prop_filterDBUsed bs = mergeStreams bs xs ys sOr b a `sComp` filterDBUsed (sOr b a) a == a
168
169prop_filterDBUsed a b = sOr b a `sComp` filterDBUsed (sOr b a) a == a
170
171compress s = filterDBUsed s s
172
173
174--takeUps :: Int -> Stream Bool -> Stream Bool
175--takeUps i = (`sComp` sFromList (replicate i True) False)
176
177--prop_takeUps (getNonNegative -> n) u = streamToList (takeUps n u) == normSem (take n $ streamToList u)
178
179--takeUps' :: Int -> Stream Bool -> Stream Bool
180--takeUps' i = sComp $ sFromList (replicate i True) False
181
182--prop_takeUps' u (getNonNegative -> n) = streamToList (takeUps' n u) == head (dropWhile ((< n) . length . filter id) (inits $ streamToList u) ++ [streamToList u])
183
184--------------------------------------------------------------- indices
185
186-- index of the first appearance of the limes
187limesIndex :: Stream a -> Int
188limesIndex = foldStream (const (+1)) (const 0)
189
190-- indices at which the stream value is True
191trueIndices :: Stream Bool -> [Int]
192trueIndices s = sFilter s [0..]
193
194prop_trueIndices (getExpDB -> u) = all (streamToFun u) $ trueIndices u
195
196invTrueIndices :: [Int] -> Stream Bool
197invTrueIndices = f 0 where
198 f i [] = Repeat False
199 f i (k: ks) = iterateN (k - i) (cons False) $ cons True $ f (k + 1) ks
200
201prop_invTrueIndices (map getNonNegative . Set.toList -> ks) = trueIndices (invTrueIndices ks) == ks
202prop_invTrueIndices' (getExpDB -> u) = u == invTrueIndices (trueIndices u)
203
204-- a Boolean stream can be seen as an index transformation function for indices 0..n
205indexTrans :: Stream Bool -> Int -> Maybe Int
206indexTrans s i = ((Just <$> sFilter s [0..]) ++ repeat Nothing) !! i
207
208-- inverse of indexTrans
209invIndexTrans :: Stream Bool -> Int -> Maybe Int
210invIndexTrans s i = case dropWhile ((< i) . snd) $ zip [0..] $ sFilter s [0..] of
211 ((x, i'): _) | i' == i -> Just x
212 _ -> Nothing
213
214prop_invIndexTrans u (getNonNegative -> i) = maybe True (==i) (indexTrans u i >>= invIndexTrans u)
215
216diffDBs as = (u, filterDBUsed u <$> as) where u = mconcat as
217
218
219------------------------------------------------------------ used/unused de bruijn indices
220
221-- which de bruijn indicies are used?
222-- semantics of DBUsed is given by trueIndices
223-- True: use index; False: skip index
224type DBUsed = Stream Bool
225
226-- invariant property: limes is False
227-- finite indicies are used; lambda expressions are decorated with this
228newtype ExpDB = ExpDB { getExpDB :: DBUsed }
229 deriving (Eq, Show)
230
231instance Arbitrary ExpDB where
232 arbitrary = ExpDB . flip sFromList False <$> arbitrary
233
234-- invariant property: limes is True
235-- finite indicies are not used; good for index shifting transformations
236newtype ShiftDB = ShiftDB { getShiftDB :: DBUsed }
237 deriving (Eq, Show)
238
239instance Arbitrary ShiftDB where
240 arbitrary = ShiftDB . flip sFromList True <$> arbitrary
241 35
242------------------------------------------------------------ de bruijn index shifting layer 36------------------------------------------------------------ de bruijn index shifting layer
243 37
@@ -278,6 +72,7 @@ mkShift e = Shift (getDBUsed e) e
278instance (Arbitrary a, GetDBUsed a) => Arbitrary (Shift a) where 72instance (Arbitrary a, GetDBUsed a) => Arbitrary (Shift a) where
279 arbitrary = upToShift <$> arbitrary 73 arbitrary = upToShift <$> arbitrary
280 74
75
281---------------- 76----------------
282 77
283-- for testing 78-- for testing
@@ -361,56 +156,86 @@ data Let e a = Let (Substs e) a
361instance (GetDBUsed e, GetDBUsed a) => GetDBUsed (Let e a) where 156instance (GetDBUsed e, GetDBUsed a) => GetDBUsed (Let e a) where
362 getDBUsed (Let m e) = getDBUsed $ ShiftLet (getDBUsed e <> mconcat (Map.elems $ getDBUsed <$> m)) m e 157 getDBUsed (Let m e) = getDBUsed $ ShiftLet (getDBUsed e <> mconcat (Map.elems $ getDBUsed <$> m)) m e
363 158
159-- let with outer shifts
160-- handles let keys removal / addition
364pattern ShiftLet :: DBUsed -> Substs a -> b -> Shift (Let a b) 161pattern ShiftLet :: DBUsed -> Substs a -> b -> Shift (Let a b)
365pattern ShiftLet u m e <- (getShiftLet -> (u, m, e)) where ShiftLet u m e = Shift (filterDBUsed (not <$> substsKeys m) u) (Let m e) 162pattern ShiftLet u m e <- (getShiftLet -> (u, m, e)) where ShiftLet u m e = Shift (filterDBUsed (not <$> substsKeys m) u) (Let m e)
366 163
367getShiftLet (Shift u (Let m e)) = (mergeStreams (substsKeys m) (Repeat True) u, m, e) 164getShiftLet (Shift u (Let m e)) = (mergeStreams (substsKeys m) (Repeat True) u, m, e)
368 165
166-- push shift into let
369-- TODO: remove Eq a 167-- TODO: remove Eq a
370pattern PShiftLet :: () => (Eq a, ShiftLike a, ShiftLike b) => Substs a -> b -> Shift (Let a b) 168pattern PushedShiftLet :: () => (Eq a, ShiftLike a, ShiftLike b) => Substs a -> b -> Shift (Let a b)
371pattern PShiftLet m e <- (pushShiftLet -> Let m e) where 169pattern PushedShiftLet m e <- (pushShiftLet -> Let m e) where
372 PShiftLet m e = ShiftLet u (filterSubsts u m) $ modDBUsed (filterDBUsed u) e 170 PushedShiftLet m e = ShiftLet u (filterSubsts u m) $ modDBUsed (filterDBUsed u) e
373 where 171 where
374 u = getDBUsed e <> mconcat (Map.elems $ getDBUsed <$> m) 172 u = getDBUsed e <> mconcat (Map.elems $ getDBUsed <$> m)
375 173
376pushShiftLet (ShiftLet u m e) = Let (expandSubsts u m) (up u e) 174pushShiftLet (ShiftLet u m e) = Let (expandSubsts u m) (up u e)
377 175
378mkLet :: (Eq a, ShiftLike a, ShiftLike b) => Substs a -> b -> Shift (Let a b) 176mkLet :: (Eq a, ShiftLike a, ShiftLike b) => Substs a -> b -> Shift (Let a b)
379mkLet m e = PShiftLet (Map.filterWithKey (\k _ -> streamToFun c k) m) e 177mkLet m e = PushedShiftLet (Map.filterWithKey (\k _ -> streamToFun (transitiveClosure (getDBUsed <$> m) $ getDBUsed e) k) m) e
178
179-- determine which let expressions are used (kinf of garbage collection)
180-- TODO: speed this up somehow
181transitiveClosure m e = limes $ sIterate f e
380 where 182 where
381 -- determine which let expressions are used (garbage collection) 183 f x = dbAnd ks $ x <> mconcat (sCatMaybes $ filterStream (Repeat Nothing) x us)
382 -- TODO: speed this up somehow 184 ks = substsKeys m
383 c = limes $ sIterate f $ getDBUsed e 185 us = substsStream m
384 where 186
385 f x = dbAnd ks $ x <> mconcat (sCatMaybes $ filterStream (Repeat Nothing) x us) 187{- TODO
386 ks = substsKeys m 188prop_mkLet_idempotent = l == f l
387 us = substsStream $ getDBUsed <$> m 189 where
190 l = mkLet m e
191 f (Let m e) = mkLet m e
192-}
193
194mkLet_test1 = mkLet m e == Shift s (Let m' e')
195 where
196 e = f [0]
197 m = Map.fromList
198 [ (0, f [10])
199 , (2, f [])
200 , (3, f [])
201 , (10, f [0, 2])
202 ]
203
204 s = invTrueIndices [7]
205 e' = f [0]
206 m' = Map.fromList
207 [ (0, f [2])
208 , (1, f [])
209 , (2, f [0, 1])
210 ]
211
212 f x = Shift (invTrueIndices x) ()
388 213
389transportIntoLet (Let m _) e = up (not <$> substsKeys m) e 214transportIntoLet (Let m _) e = up (not <$> substsKeys m) e
390 215
391----------------------------------------------------------------- MaybeLet 216----------------------------------------------------------------- MaybeLet
392 217
393data MaybeLet a b c 218data MaybeLet a b
394 = HasLet (Let a (Shift c)) 219 = HasLet (Let a (Shift b))
395 | NoLet b 220 | NoLet b
396 deriving (Show, Eq) 221 deriving (Show, Eq, Functor)
397
398type MaybeLet' a b = MaybeLet a b b
399 222
400maybeLet :: (Eq a, ShiftLike a) => Shift (Let a (Shift b)) -> Shift (MaybeLet' a b) 223maybeLet :: (Eq a, ShiftLike a) => Shift (Let a (Shift b)) -> Shift (MaybeLet a b)
401maybeLet l@(Shift u (Let m e)) 224maybeLet l@(Shift u (Let m e))
402 | Map.null m = up u $ NoLet <$> e 225 | Map.null m = up u $ NoLet <$> e
403 | otherwise = HasLet <$> l 226 | otherwise = HasLet <$> l
404 227
405joinLets :: (Eq a, ShiftLike a) => MaybeLet' a (MaybeLet' a b) -> MaybeLet' a b 228joinLets :: (Eq a, ShiftLike a) => MaybeLet a (MaybeLet a b) -> MaybeLet a b
406joinLets (NoLet e) = e 229joinLets (NoLet e) = e
407joinLets (HasLet (Let m (Shift s' (NoLet e)))) = HasLet $ Let m $ Shift s' e 230joinLets (HasLet (Let m (Shift s' (NoLet e)))) = HasLet $ Let m $ Shift s' e
408joinLets (HasLet (Let m (Shift s' (HasLet (Let m' e))))) 231joinLets (HasLet (Let m (Shift s' (HasLet (Let m' e)))))
409 = HasLet $ Let (expandSubsts (not <$> substsKeys sm) m <> sm) se 232 = HasLet $ Let (expandSubsts (not <$> substsKeys sm) m <> sm) se
410 where 233 where
411 (PShiftLet sm se) = Shift s' (Let m' e) 234 (PushedShiftLet sm se) = Shift s' (Let m' e)
412 235
413instance (GetDBUsed a, GetDBUsed b, GetDBUsed c) => GetDBUsed (MaybeLet a b c) where 236-- TODO: test joinLets
237
238instance (GetDBUsed a, GetDBUsed b) => GetDBUsed (MaybeLet a b) where
414 getDBUsed = \case 239 getDBUsed = \case
415 NoLet a -> getDBUsed a 240 NoLet a -> getDBUsed a
416 HasLet x -> getDBUsed x 241 HasLet x -> getDBUsed x
@@ -448,7 +273,17 @@ type RHSExp = Exp Void
448-- left-hand-side expression (allows RHS constructor) 273-- left-hand-side expression (allows RHS constructor)
449type LHSExp = Exp RHSExp 274type LHSExp = Exp RHSExp
450 275
451type WithLet a = MaybeLet (Shift LHSExp) a a 276-- TODO: make this constant time operation
277lhs :: RHSExp -> LHSExp
278lhs = \case
279 ELit l -> ELit l
280 EVar -> EVar
281 ELamD e -> ELamD $ lhs e
282 ELam l -> ELam $ lhs <$> l
283 EApp a b -> EApp (lhs <$> a) (lhs <$> b)
284 RHS _ -> error "lhs: impossible"
285
286type WithLet a = MaybeLet (Shift LHSExp) a
452 287
453-------------------------------------------------------- 288--------------------------------------------------------
454 289
@@ -474,33 +309,44 @@ newtype SimpleExp = SimpleExp { getSimpleExp :: SLExp }
474 309
475instance Arbitrary SimpleExp where 310instance Arbitrary SimpleExp where
476 arbitrary = fmap SimpleExp $ oneof 311 arbitrary = fmap SimpleExp $ oneof
477 [ var . getNonNegative <$> arbitrary 312 [ Var . getNonNegative <$> arbitrary
478 , Int <$> arbitrary 313 , Int <$> arbitrary
479 , app <$> (getSimpleExp <$> arbitrary) <*> (getSimpleExp <$> arbitrary) 314 , app <$> (getSimpleExp <$> arbitrary) <*> (getSimpleExp <$> arbitrary)
480 , lam <$> (getSimpleExp <$> arbitrary) 315 , lam <$> (getSimpleExp <$> arbitrary)
481 ] 316 ]
482 317
318-- does no reduction
319pattern SLLit :: Lit -> SLExp
483pattern SLLit l <- (getLit -> Just l) where SLLit = Shift mempty . NoLet . ELit 320pattern SLLit l <- (getLit -> Just l) where SLLit = Shift mempty . NoLet . ELit
484 321
485getLit :: SLExp -> Maybe Lit 322getLit :: SLExp -> Maybe Lit
486getLit (Shift _ (NoLet (ELit l))) = Just l 323getLit (Shift (Repeat False) (NoLet (ELit l))) = Just l
487getLit (Shift _ (HasLet (Let _ (Shift _ (ELit l))))) = Just l 324getLit (Shift _ (HasLet (Let _ (Shift _ (ELit l))))) = error "getLit: impossible: literals does not depend on variables"
488getLit _ = Nothing 325getLit _ = Nothing
489 326
490pattern Int i = SLLit (LInt i) 327pattern Int i = SLLit (LInt i)
491 328
492var :: Int -> SLExp 329-- TODO: should it reduce on pattern match?
493var i = fmap NoLet $ up_ 0 i $ mkShift EVar 330pattern Var :: Int -> SLExp
331pattern Var i <- (getVar -> Just i) where Var i = fmap NoLet $ up_ 0 i $ mkShift EVar
494 332
495prop_upVar (getNonNegative -> k) (getNonNegative -> n) (getNonNegative -> i) = up_ k n (var i) == var (if k <= i then n + i else i) 333getVar (Shift u (NoLet EVar)) = Just $ fromMaybe (error "getVar: impossible") $ listToMaybe $ trueIndices u
496prop_downVar (getNonNegative -> k) (getNonNegative -> i) = down_ k (var i) == case compare k i of LT -> Just (var $ i-1); EQ -> Nothing; GT -> Just (var i) 334getVar (Shift _ (HasLet (Let _ (Shift _ _)))) = error "getVar: TODO"
335getVar _ = Nothing
336
337prop_Var (getNonNegative -> i) = case (Var i) of Var j -> i == j
338
339prop_upVar (getNonNegative -> k) (getNonNegative -> n) (getNonNegative -> i) = up_ k n (Var i) == Var (if k <= i then n + i else i)
340prop_downVar (getNonNegative -> k) (getNonNegative -> i) = down_ k (Var i) == case compare k i of LT -> Just (Var $ i-1); EQ -> Nothing; GT -> Just (Var i)
497 341
498lam :: SLExp -> SLExp 342lam :: SLExp -> SLExp
499lam (Shift u e) = Shift (sTail u) $ if sHead u then eLam e else eLamD e 343lam (Shift u e) = Shift (sTail u) $ if sHead u then eLam e else eLamD e
500 where 344 where
501 eLam (NoLet e) = NoLet $ ELam $ NoLet e 345 eLam (NoLet e) = NoLet $ ELam $ NoLet e
502 -- TODO: improve this by let-floating 346 -- TODO: improve this by let-floating
503 eLam (HasLet (Let m (Shift u x))) = NoLet $ ELam (HasLet (Let m (Shift u x))) 347 eLam (HasLet (Let m e)) = NoLet $ ELam (HasLet (Let m{-(filterSubsts (not <$> c) m)-} e))
348 where
349 c = transitiveClosure (getDBUsed <$> m) $ Cons True $ Repeat False
504 350
505 eLamD (NoLet e) = NoLet $ ELamD e 351 eLamD (NoLet e) = NoLet $ ELamD e
506 -- TODO: review 352 -- TODO: review
@@ -508,6 +354,28 @@ lam (Shift u e) = Shift (sTail u) $ if sHead u then eLam e else eLamD e
508 where 354 where
509 ul = Cons False $ Repeat True 355 ul = Cons False $ Repeat True
510 356
357lam_test_let = lam $ lets_ m e -- == Shift s (Let m' e')
358 where
359 f (HasLet (Let m a)) = HasLet $ Let m a
360
361 e = Var 0 `app` Var 1 `app` Var 10
362 m = Map.fromList
363 [ (0, Var 13)
364 , (2, Var 1)
365 , (3, Var 1)
366 , (10, Var 0 `app` Var 2)
367 ]
368{-
369 s = invTrueIndices [7]
370 e' = f [0]
371 m' = Map.fromList
372 [ (0, f [2])
373 , (1, f [])
374 , (2, f [0, 1])
375 ]
376-}
377-- f x = Shift (invTrueIndices x) ()
378
511app :: SLExp -> SLExp -> SLExp 379app :: SLExp -> SLExp -> SLExp
512app (Shift ua (NoLet a)) (Shift ub (NoLet b)) 380app (Shift ua (NoLet a)) (Shift ub (NoLet b))
513 = Shift u $ NoLet $ EApp (Shift (filterDBUsed u ua) a) (Shift (filterDBUsed u ub) b) 381 = Shift u $ NoLet $ EApp (Shift (filterDBUsed u ua) a) (Shift (filterDBUsed u ub) b)
@@ -530,6 +398,13 @@ app x y = f x y
530 lb'@(Let mb eb) = pushShiftLet $ Shift ulb' lb 398 lb'@(Let mb eb) = pushShiftLet $ Shift ulb' lb
531 xa = transportIntoLet lb' $ Shift ula' la 399 xa = transportIntoLet lb' $ Shift ula' la
532 400
401-- TODO: handle lets inside
402lets_ :: Substs SLExp -> SLExp -> SLExp
403lets_ m e = lets (f <$> m) e
404 where
405 f :: SLExp -> Shift LHSExp
406 f (Shift u (NoLet e)) = Shift u $ lhs e
407
533lets :: Substs (Shift LHSExp) -> SLExp -> SLExp 408lets :: Substs (Shift LHSExp) -> SLExp -> SLExp
534lets m e = fmap joinLets $ maybeLet $ mkLet m e 409lets m e = fmap joinLets $ maybeLet $ mkLet m e
535 410
@@ -559,7 +434,7 @@ pushShift (Shift u e) = ExpS $ case e of
559 LHS a b -> LHS_ a (up u <$> b) -- ??? $ SData (pushShift $ Shift u c) 434 LHS a b -> LHS_ a (up u <$> b) -- ??? $ SData (pushShift $ Shift u c)
560-- Delta x -> Delta_ $ SData x 435-- Delta x -> Delta_ $ SData x
561 436
562prop_var (getNonNegative -> i) = case pushShift (fromLet $ var i) of 437prop_Var (getNonNegative -> i) = case pushShift (fromLet $ Var i) of
563 ExpS (EVar i') -> i == i' 438 ExpS (EVar i') -> i == i'
564 _ -> False 439 _ -> False
565 440
@@ -567,7 +442,7 @@ prop_app (getSimpleExp -> a) (getSimpleExp -> b) = case pushShift $ fromLet $ ap
567 ExpS (EApp a' b') -> (a', b') == (fromLet a, fromLet b) 442 ExpS (EApp a' b') -> (a', b') == (fromLet a, fromLet b)
568 _ -> False 443 _ -> False
569 444
570--prop_lam (getNonNegative -> i) = elimShift undefined undefined undefined (==i) (var i) 445--prop_lam (getNonNegative -> i) = elimShift undefined undefined undefined (==i) (Var i)
571 446
572--prop_pushShift (Shift u e) = 447--prop_pushShift (Shift u e) =
573 448
@@ -600,7 +475,7 @@ pushLet' (Shift u l) = case l of
600 -- ELamD a -> ELamD $ NoLet a 475 -- ELamD a -> ELamD $ NoLet a
601 LHS a b -> LHS_ a ((fmap NoLet . up u) <$> b) 476 LHS a b -> LHS_ a ((fmap NoLet . up u) <$> b)
602 HasLet l -> case Shift u l of 477 HasLet l -> case Shift u l of
603 PShiftLet m e -> case pushShift e of 478 PushedShiftLet m e -> case pushShift e of
604 ExpS e' -> case e' of 479 ExpS e' -> case e' of
605 EApp a b -> ExpL $ EApp (fmap HasLet (mkLet m a)) (fmap HasLet (mkLet m b)) 480 EApp a b -> ExpL $ EApp (fmap HasLet (mkLet m a)) (fmap HasLet (mkLet m b))
606 ELit i -> ExpL $ ELit i 481 ELit i -> ExpL $ ELit i
@@ -634,7 +509,7 @@ hnf e = case pushLet' e of
634----------------------------------------------------------------------------------- 509-----------------------------------------------------------------------------------
635-} 510-}
636idE :: SLExp 511idE :: SLExp
637idE = lam $ var 0 512idE = lam $ Var 0
638{- 513{-
639add :: SLExp 514add :: SLExp
640add = NoLet <$> mkShift (LHS "add" []) -- $ ELam $ NoLet $ ELam $ NoLet $ Delta f) 515add = NoLet <$> mkShift (LHS "add" []) -- $ ELam $ NoLet $ ELam $ NoLet $ Delta f)
@@ -652,7 +527,7 @@ example2 = app (app add (Int 10)) (Int 5)
652----------------------------------------------------------------- run all tests 527----------------------------------------------------------------- run all tests
653-} 528-}
654return [] 529return []
655runTests = $quickCheckAll 530runTests | mkLet_test1 = $quickCheckAll
656 531
657{- 532{-
658TODO 533TODO
@@ -666,7 +541,7 @@ TODO
666 - up, down 541 - up, down
667 - subst 542 - subst
668 - constructions 543 - constructions
669 - lam, pi, app, var, lit, ... 544 - lam, pi, app, Var, lit, ...
670 - eliminations 545 - eliminations
671 546
672- intergrate into the compiler 547- intergrate into the compiler
diff --git a/prototypes/Stream.hs b/prototypes/Stream.hs
new file mode 100644
index 00000000..4d68d3b0
--- /dev/null
+++ b/prototypes/Stream.hs
@@ -0,0 +1,248 @@
1{-# language ScopedTypeVariables #-}
2{-# language LambdaCase #-}
3{-# language TypeOperators #-}
4{-# language TypeFamilies #-}
5{-# language ViewPatterns #-}
6{-# language PatternGuards #-}
7{-# language PatternSynonyms #-}
8{-# language RankNTypes #-}
9{-# language DataKinds #-}
10{-# language KindSignatures #-}
11{-# language GADTs #-}
12{-# language DeriveFunctor #-}
13{-# language DeriveGeneric #-}
14{-# language DefaultSignatures #-}
15{-# language FlexibleInstances #-}
16{-# language FlexibleContexts #-}
17{-# language TemplateHaskell #-} -- for testing
18{-# language NoMonomorphismRestriction #-}
19module Stream where
20
21import Data.Monoid
22import Data.Maybe
23import Data.List
24import Data.Map (Map)
25import qualified Data.Map as Map
26import qualified Data.Set as Set
27import Control.Monad
28import Control.Arrow hiding (app)
29import Test.QuickCheck
30import Test.QuickCheck.Function
31import GHC.Generics
32import Debug.Trace
33
34------------------------------------------------------------ utils
35
36iterateN i f x = iterate f x !! i
37
38(<&>) = flip (<$>)
39
40data Void
41
42instance Eq Void where (==) = error "(==) @Void"
43instance Show Void where show = error "show @Void"
44
45{- used later?
46-- supplementary data: data with no semantic relevance
47newtype SData a = SData a
48instance Show (SData a) where show _ = "SData"
49instance Eq (SData a) where _ == _ = True
50instance Ord (SData a) where _ `compare` _ = EQ
51-}
52
53------------------------------------------------------------ streams
54
55-- streams with constant tails
56-- invariant property: Repeat is used when possible (see cons)
57data Stream a
58 = Cons a (Stream a)
59 | Repeat a
60 deriving (Eq, Show, Functor) -- Functor is not proper, may break invariant
61
62-- smart constructor to construct normal form of streams
63cons b (Repeat b') | b == b' = Repeat b'
64cons b x = Cons b x
65
66-- stream head
67sHead (Cons a _) = a
68sHead (Repeat a) = a
69
70-- stream tail
71sTail (Cons _ a) = a
72sTail (Repeat a) = Repeat a
73
74instance Applicative Stream where
75 pure a = Repeat a
76 -- (<*>) is not proper, may break invariant
77 Repeat f <*> Repeat a = Repeat $ f a
78 x <*> y = Cons{-should be cons-} (sHead x $ sHead y) (sTail x <*> sTail y)
79
80foldStream :: (b -> a -> a) -> (b -> a) -> Stream b -> a
81foldStream f g (Cons b u) = f b (foldStream f g u)
82foldStream f g (Repeat b) = g b
83
84-- final value in the stream
85limes :: Stream a -> a
86limes = foldStream (flip const) id
87
88prop_limes (getNonNegative -> n) = limes (sFromList [0..n-1] n) == n
89
90-- replace limes by given stream
91sCont :: Eq a => Stream a -> (a -> Stream a) -> Stream a
92sCont as f = foldStream cons f as
93
94-- semantics of Stream
95streamToList :: Stream a -> [a]
96streamToList = foldStream (:) repeat
97
98streamToFun :: Stream a -> Int -> a
99streamToFun u i = streamToList u !! i
100
101sFromList :: Eq a => [a] -> a -> Stream a
102sFromList xs b = foldr cons (Repeat b) xs
103
104instance (Arbitrary a, Eq a) => Arbitrary (Stream a) where
105 arbitrary = sFromList <$> arbitrary <*> arbitrary
106
107-- iterate on stream
108sIterate :: Eq a => (a -> a) -> a -> Stream a
109sIterate f x
110 | y == x = Repeat x
111 | otherwise = Cons x $ sIterate f y
112 where
113 y = f x
114
115sCatMaybes :: Stream (Maybe a) -> [a]
116sCatMaybes = foldStream (\m s -> maybe s (:s) m) (maybe [] repeat)
117
118---------------------------------------------------------- operations involving Boolean streams
119
120mergeStreams :: Eq a => Stream Bool -> Stream a -> Stream a -> Stream a
121mergeStreams (Cons True u) as bs = cons (sHead as) $ mergeStreams u (sTail as) bs
122mergeStreams (Cons False u) as bs = cons (sHead bs) $ mergeStreams u as (sTail bs)
123mergeStreams (Repeat True) as bs = as
124mergeStreams (Repeat False) as bs = bs
125
126sFilter :: Stream Bool -> [a] -> [a]
127sFilter (Cons True u) is = take 1 is ++ sFilter u (drop 1 is)
128sFilter (Cons False u) is = sFilter u (drop 1 is)
129sFilter (Repeat True) is = is
130sFilter (Repeat False) is = []
131
132-- sFilter for streams
133-- the first stream is used when no more element can pass the filter
134filterStream :: Eq a => Stream a -> Stream Bool -> Stream a -> Stream a
135filterStream d (Cons True s) as = cons (sHead as) $ filterStream d s $ sTail as
136filterStream d (Cons False s) as = filterStream d s $ sTail as
137filterStream d (Repeat True) as = as
138filterStream d (Repeat False) as = d
139
140sOr :: Stream Bool -> Stream Bool -> Stream Bool
141sOr (Cons b u) (Cons b' u') = cons (b || b') $ sOr u u'
142sOr (Repeat False) u = u
143sOr (Repeat True) u = Repeat True
144sOr u (Repeat False) = u
145sOr u (Repeat True) = Repeat True
146
147prop_sOr_idemp a = sOr a a == a
148prop_sOr_comm a b = sOr a b == sOr b a
149
150dbAnd a b = not <$> sOr (not <$> a) (not <$> b)
151
152instance Monoid (Stream Bool) where
153 mempty = Repeat False
154 mappend = sOr
155
156prop_StreamBool_monoid_left (a :: Stream Bool) = mempty <> a == a
157prop_StreamBool_monoid_right (a :: Stream Bool) = a <> mempty == a
158prop_StreamBool_monoid_assoc (a :: Stream Bool) b c = (a <> b) <> c == a <> (b <> c)
159
160-- composition of (Stream Bool) values (by sFilter semantics)
161sComp :: Stream Bool -> Stream Bool -> Stream Bool
162sComp bs as = mergeStreams bs as $ Repeat False
163
164prop_sComp a b xs = sFilter (sComp a b) xs == (sFilter b . sFilter a) xs
165prop_sComp_trans a b (getNonNegative -> i) = indexTrans (sComp a b) i == (indexTrans a =<< indexTrans b i)
166
167filterDBUsed :: Stream Bool -> Stream Bool -> Stream Bool
168filterDBUsed = filterStream $ Repeat False
169
170--prop_filterDBUsed bs = mergeStreams bs xs ys sOr b a `sComp` filterDBUsed (sOr b a) a == a
171
172prop_filterDBUsed a b = sOr b a `sComp` filterDBUsed (sOr b a) a == a
173
174compress s = filterDBUsed s s
175
176
177--takeUps :: Int -> Stream Bool -> Stream Bool
178--takeUps i = (`sComp` sFromList (replicate i True) False)
179
180--prop_takeUps (getNonNegative -> n) u = streamToList (takeUps n u) == normSem (take n $ streamToList u)
181
182--takeUps' :: Int -> Stream Bool -> Stream Bool
183--takeUps' i = sComp $ sFromList (replicate i True) False
184
185--prop_takeUps' u (getNonNegative -> n) = streamToList (takeUps' n u) == head (dropWhile ((< n) . length . filter id) (inits $ streamToList u) ++ [streamToList u])
186
187--------------------------------------------------------------- indices
188
189-- index of the first appearance of the limes
190limesIndex :: Stream a -> Int
191limesIndex = foldStream (const (+1)) (const 0)
192
193-- indices at which the stream value is True
194trueIndices :: Stream Bool -> [Int]
195trueIndices s = sFilter s [0..]
196
197prop_trueIndices (getExpDB -> u) = all (streamToFun u) $ trueIndices u
198
199invTrueIndices :: [Int] -> Stream Bool
200invTrueIndices = f 0 where
201 f i [] = Repeat False
202 f i (k: ks) = iterateN (k - i) (cons False) $ cons True $ f (k + 1) ks
203
204prop_invTrueIndices (map getNonNegative . Set.toList -> ks) = trueIndices (invTrueIndices ks) == ks
205prop_invTrueIndices' (getExpDB -> u) = u == invTrueIndices (trueIndices u)
206
207-- a Boolean stream can be seen as an index transformation function for indices 0..n
208indexTrans :: Stream Bool -> Int -> Maybe Int
209indexTrans s i = ((Just <$> sFilter s [0..]) ++ repeat Nothing) !! i
210
211-- inverse of indexTrans
212invIndexTrans :: Stream Bool -> Int -> Maybe Int
213invIndexTrans s i = case dropWhile ((< i) . snd) $ zip [0..] $ sFilter s [0..] of
214 ((x, i'): _) | i' == i -> Just x
215 _ -> Nothing
216
217prop_invIndexTrans u (getNonNegative -> i) = maybe True (==i) (indexTrans u i >>= invIndexTrans u)
218
219diffDBs as = (u, filterDBUsed u <$> as) where u = mconcat as
220
221------------------------------------------------------------ used/unused de bruijn indices
222
223-- which de bruijn indicies are used?
224-- semantics of DBUsed is given by trueIndices
225-- True: use index; False: skip index
226type DBUsed = Stream Bool
227
228-- invariant property: limes is False
229-- finite indicies are used; lambda expressions are decorated with this
230newtype ExpDB = ExpDB { getExpDB :: DBUsed }
231 deriving (Eq, Show)
232
233instance Arbitrary ExpDB where
234 arbitrary = ExpDB . flip sFromList False <$> arbitrary
235
236-- invariant property: limes is True
237-- finite indicies are not used; good for index shifting transformations
238newtype ShiftDB = ShiftDB { getShiftDB :: DBUsed }
239 deriving (Eq, Show)
240
241instance Arbitrary ShiftDB where
242 arbitrary = ShiftDB . flip sFromList True <$> arbitrary
243
244------------------------------------------------------------------
245
246return []
247main = $quickCheckAll
248