-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathLattice.hs
107 lines (90 loc) · 2.9 KB
/
Lattice.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
{-# LANGUAGE NoMonomorphismRestriction #-}
module Lattice where
import qualified Data.Set as S
import qualified Data.Map as M
class SetLike s where
difference :: s -> s -> s
intersection :: s -> s -> s
union :: s -> s -> s
{-class MapLike (m x) where-}
{--- differenceWith :: m -> m -> m-}
{-intersectionWith :: () -> m -> m -> m-}
{-unionWith :: m -> m -> m-}
{-lookup :: m -> k -> a-}
instance (Ord key) => SetLike (S.Set key) where
difference = S.difference
intersection = S.intersection
union = S.union
instance (Ord key) => SetLike (M.Map key val) where
difference = M.difference
intersection = M.intersection
union = M.union
{-instance MapLike (M.Map key val) where-}
{--- differenceWith = M.differenceWith-}
{-intersectionWith = M.intersectionWith-}
{-unionWith = M.unionWith-}
{-lookup = M.lookup-}
class Lattice a where
(<:) :: a -> a -> Bool
join :: a -> a -> a
meet :: a -> a -> a
class (Lattice a) => LowerBoundedLattice a where
bottom :: a
class (Lattice a) => UpperBoundedLattice a where
top :: a
instance Lattice Bool where
False <: x = True
True <: False = False
True <: True = True
join False x = x
join True x = True
meet False x = False
meet True x = x
instance LowerBoundedLattice Bool where
bottom = False
-- least fixed points
data Scc key = Scc { sccPending, sccFinished :: S.Set key, sccChanged :: Bool }
newScc = Scc S.empty S.empty False
data LFixSt key val = LFixSt { finished, pending, unfinished :: M.Map key val,
scc :: Scc }
getFixSt = get
putFixSt = put
fixLookup key = do
st <- getFixSt
case lkup $ finished st of
Just val -> return val
Nothing ->
case lkup $ pending st of
Just val -> do
let st' = st{sccPending=S.insert key $ sccPending st}
putFixSt st'
return val
Nothing ->
let val = case lkup $ unfinished st of
Just val -> val
Nothing -> bottom
let sccParent = scc st
let st0 = st{pending=M.insert key val $ pending st, scc = newScc}
putFixSt st0
-- val = f key
st <- getFixSt
let sccCur = scc st
let sccCur = sccCur{sccPending=S.delete key $ sccPending sccCur}
if not . S.null $ sccPending sccCur then do
let st1' = st{sccFinished=S.insert key sccFinished}
putFixSt st1'
else
let fin = sccFinished st
if not $ S.null fin then
let pending' = S.difference st1 fin
if sccChanged then
let st2 = st1{pending=pending'}
putFixSt st2
fixLookup key
{-
- if recursive and any member of SCC changed: pending=pending-sccFinished; re-evaluate
- otherwise move SCC/individual to finished
- return value
- -}
return val
where lkup = M.lookup key