-
Notifications
You must be signed in to change notification settings - Fork 0
/
FunDep.hs
166 lines (125 loc) · 6.37 KB
/
FunDep.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
{-# LANGUAGE GADTs, DataKinds, KindSignatures, TypeOperators, TypeFamilies,
MultiParamTypeClasses, FlexibleInstances, PolyKinds,
FlexibleContexts, UndecidableInstances, ConstraintKinds,
ScopedTypeVariables, TypeInType, TypeOperators, StandaloneDeriving,
ConstraintKinds, TypeApplications #-}
module FunDep where
import Common
import GHC.TypeLits
import Data.Type.Bool
import Data.Type.Set
import Label
data FunDep where
FunDep :: [Symbol] -> [Symbol] -> FunDep
instance (Recoverable l [String], Recoverable r [String]) =>
Recoverable ('FunDep l r) ([String], [String]) where
recover Proxy = (recover @l Proxy, recover @r Proxy)
type family (-->) (left :: [Symbol]) (right :: [Symbol]) :: FunDep where
xs --> ys = ('FunDep (SymAsSet xs) (SymAsSet ys) :: FunDep)
class FunDepKnown f where
left :: f -> [String]
right :: f -> [String]
--instance (LabListKnown (LabList l), LabListKnown (LabList r)) => FunDepKnown (FunDep ('LabList :: LabList l) ('LabList :: LabList r)) where
-- left _ = labListVal (LabList :: LabList l)
-- right _ = labListVal (LabList :: LabList r)
-- instance FunDepKnown (FunDep l r) => Show (FunDep l r) where
-- show f = ppList " " (left f) ++ " --> " ++ ppList " " (right f)
type Fd1 = '["A", "B"] --> '["C"]
type Fd2 = '["C"] --> '["D", "E"]
type Fd3 = '["F"] --> '["G"]
type Fd4 = '["D"] --> '["H"]
type Fd5 = '["D"] --> '["I"]
type Fd6 = '["B"] --> '["H"]
type Fd7 = '["C"] --> '["D"]
type Fds1 = '[Fd1, Fd2, Fd3, Fd4]
type Fds2 = '[Fd1, Fd2, Fd3, Fd4, Fd5]
type Fds3 = '[Fd1, Fd2, Fd3, Fd4, Fd6]
type Fds4 = '[Fd1, Fd7, Fd3, Fd4]
data FunDepList :: [k] -> * where
FunDepList :: FunDepList fds
type family Cols (f :: [FunDep]) :: [Symbol] where
Cols '[] = '[]
Cols ('FunDep l r ': fds) = l :++ r :++ Cols fds
type family Left (f :: FunDep) :: [Symbol] where
Left ('FunDep left _) = left
type family Right (f :: FunDep) :: [Symbol] where
Right ('FunDep _ right) = right
type family Rights (f :: [FunDep]) :: [[Symbol]] where
Rights '[] = '[]
Rights (x ': xs) = Right x ': Rights xs
type family Lefts (f :: [FunDep]) :: [[Symbol]] where
Lefts '[] = '[]
Lefts (x ': xs) = Left x ': Lefts xs
-- from label list to fundep list
type family Closure (from :: [Symbol]) (to :: [FunDep]) :: [Symbol] where
Closure fr '[] = fr
Closure fr (f ': fds) = If (IsSubset (Left f) fr) (SymUnion (Right f) (Closure fr fds)) (Closure fr fds)
type family TransClosure (from :: [Symbol]) (to :: [FunDep]) :: [Symbol] where
TransClosure fr fds = TransClosureF fr fds (Len fds)
type family TransClosureF (from :: [Symbol]) (to :: [FunDep]) fuel :: [Symbol] where
TransClosureF fr fds 0 = fr
TransClosureF fr fds n = (TransClosureF (Closure fr fds) fds (n-1))
type family OutputsL (fds :: [FunDep]) where
OutputsL '[] = '[]
OutputsL (fd ': fds) = (SetSubtract (Right fd) (Left fd)) :++ OutputsL fds
type family Outputs (fds :: [FunDep]) where
Outputs fds = SymAsSet (OutputsL fds)
type family IsInTreeForm (fds :: [FunDep]) where
IsInTreeForm fds =
AllDisjoint (Rights fds) && AllDisjoint (SLAsSet (Rights fds :++ Lefts fds)) && IsAcyclic fds
type InTreeForm fds = OkOrError (IsInTreeForm fds) ('Text "The functional dependencies are not in tree form.")
-- Cycle checks
type family StartingPointsEx (lefts :: [[Symbol]]) (rights :: [[Symbol]]) :: [[Symbol]] where
StartingPointsEx '[] _ = '[]
StartingPointsEx (x ': xs) rights = If (DisjointFromAll x rights) (x ': StartingPointsEx xs rights) (StartingPointsEx xs rights)
type family StartingPoints (fds :: [FunDep]) :: [[Symbol]] where
StartingPoints fds = SLAsSet (StartingPointsEx (Lefts fds) (Rights fds))
type family FollowRes (isel :: Bool) (from :: [[Symbol]]) (fd :: FunDep) (sub :: ([[Symbol]], [FunDep], [FunDep])) :: ([[Symbol]], [FunDep], [FunDep]) where
FollowRes 'True from fd '(visited, vfds, fds) = '(Right fd ': visited, fd ': vfds, fds)
FollowRes 'False from fd '(visited, vfds, fds) = '(visited, vfds, fd ': fds)
type family Follow (from :: [[Symbol]]) (fds :: [FunDep]) :: ([[Symbol]], [FunDep], [FunDep]) where
Follow from '[] = '(from, '[], '[])
Follow from (fd ': fds) = FollowRes (IsElement (Left fd) from) from fd (Follow from fds)
type family IsAcyclicEx (res :: ([[Symbol]], [FunDep], [FunDep])) (fuel :: Nat) :: Bool where
IsAcyclicEx '(syms, _, '[]) _ = AllDisjoint syms
IsAcyclicEx _ 0 = 'False
IsAcyclicEx '(syms, _, fds) n = IsAcyclicEx (Follow syms fds) (n-1)
type family IsAcyclic (fds :: [FunDep]) :: Bool where
IsAcyclic fds = IsAcyclicEx '(StartingPoints fds, '[], fds) (Len fds)
-- FDS sanitation
type family RightSplit (right :: [Symbol]) (lefts :: [[Symbol]]) :: [[Symbol]] where
RightSplit '[] _ = '[]
RightSplit r '[] = '[r]
RightSplit r (x ': xs) = If (IsSubset x r) (x ': RightSplit (SetSubtract r x) xs) (RightSplit r xs)
type family MakeFDs (left :: [Symbol]) (rights :: [[Symbol]]) :: [FunDep] where
MakeFDs _ '[] = '[]
MakeFDs left (r ': rs) = 'FunDep left r ': MakeFDs left rs
type family FDSRightSplitEx (fds :: [FunDep])
(lefts :: [[Symbol]]) :: [FunDep] where
FDSRightSplitEx '[] _ = '[]
FDSRightSplitEx (fd ': fds) lefts =
MakeFDs (Left fd) (RightSplit (Right fd) lefts) :++
FDSRightSplitEx fds lefts
type family SplitFDs (fds :: [FunDep]) :: [FunDep] where
SplitFDs fds = FDSRightSplitEx fds (Lefts fds)
type family DropKey (dr :: [Symbol]) (fds :: [FunDep]) :: [Symbol] where
DropKey dr ('FunDep left dr ': fds) = left
DropKey dr (_ ': fds) = DropKey dr fds
type family DropColumnEx (dr :: [Symbol]) (key :: [Symbol])
(fds :: [FunDep]) :: [FunDep] where
DropColumnEx _ _ '[] = '[]
DropColumnEx dr key ('FunDep dr right ': fds) =
'FunDep key right ': DropColumnEx dr key fds
DropColumnEx dr key ('FunDep left right ': fds) =
AddIf (Not (IsSubset right dr))
('FunDep left (Subtract right dr))
(DropColumnEx dr key fds)
type family DropColumn (dr :: [Symbol]) (fds :: [FunDep]) :: [FunDep] where
DropColumn dr fds = DropColumnEx dr (DropKey dr fds) fds
type family TopologicalSortEx (res :: ([[Symbol]], [FunDep], [FunDep])) :: [FunDep] where
IsAcyclicEx '(_, vfds, '[]) = vfds
IsAcyclicEx '(syms, vfds, fds) = vfds :++ TopologicalSortEx (Follow syms fds)
type family TopologicalSort (fds :: [FunDep]) :: [FunDep] where
TopologicalSort fds = TopologicalSortEx '(StartingPoints fds, '[], fds)
type family Roots (fds :: [FunDep]) :: [Symbol] where
Roots fds = Concat (StartingPoints fds)