@@ -3,12 +3,14 @@
33
44module Data.Schematic.Migration where
55
6+import Data.Kind
67import Data.Schematic.Path
78import Data.Schematic.Schema
89import Data.Schematic.Utils
910import Data.Singletons.Prelude hiding (All)
1011import Data.Singletons.TypeLits
11−import Data.Vinyl
12+import Data.Vinyl hiding (Dict)
13+
1214
1315data Path
1416 = PKey Symbol -- traverse into the object by key
@@ -70,14 +72,65 @@ type family SchemaByRevision (r :: Revision) (vd :: Versioned) :: Schema where
7072 SchemaByRevision r ('Versioned s (m ': ms)) =
7173 SchemaByRevision r ('Versioned (Snd (ApplyMigration m s)) ms)
7274
73−type family TopVersion (vd :: Versioned) :: Schema where
74− TopVersion ('Versioned s '[]) = s
75− TopVersion ('Versioned s (m ': ms)) =
76− TopVersion ('Versioned (Snd (ApplyMigration m s)) ms)
75+-- type family Reverse (acc :: [(Revision, Schema)]) (rs :: [(Revision, Schema)]) :: [(Revision, Schema)] where
76+-- Reverse acc '[] = acc
77+-- Reverse acc (h ': tl) = Reverse (h ': acc) tl
78+
79+type family Migratable (rs :: [(Revision, Schema)]) :: Constraint where
80+ -- constraint duplication
81+ Migratable ('(r,s) ': '(r', s') ': tl) =
82+ (Known (Sing s), MigrateSchema s s', TopLevel s, Migratable ('(r',s') ': tl))
83+ Migratable ('(r,s) ': '[]) = (TopLevel s, Known (Sing s))
84+ -- Migratable '[] = ('True ~ 'False)
85+
86+-- data NonEmpty a = a :| [a]
87+
88+-- data instance Sing (ne :: NonEmpty a) where
89+-- SNECons :: Known (Sing e), Known (Sing l))=> Sing (e :: k) -> Sing (l :: [k]) -> Sing (e ':| l)
90+
91+data Revisions = Revisions
92+ Schema -- top version
93+ [(Revision, Schema)]
94+
95+data instance Sing (rs :: Revisions) where
96+ SRevisions
97+ :: (Known (Sing schema), Known (Sing rps), Known (Dict (ElemOf schema prs)))
98+ => Sing schema
99+ -> Sing rps
100+ -> Sing ('Revisions schema rps)
101+
102+-- -- | Heterogenous list with a proof of element schema included in the list itself.
103+-- data ElemList :: k -> [k] -> Type where
104+-- Singl :: Known (Sing schema) => Sing schema -> ElemList schema '[schema]
105+-- KeepProof :: Known (Sing new) => Sing new -> ElemList schema ss -> ElemList schema (new ': ss)
106+-- NewProof :: Known (Sing new) => Sing new -> ElemList schema ss -> ElemList new (new ': ss)
107+
108+type family ElemOf (e :: k) (l :: [(a,k)]) :: Constraint where
109+ ElemOf e '[] = 'True ~ 'False
110+ ElemOf e ( '(a, e) ': es) = ()
111+ ElemOf e (n ': es) = ElemOf e es
112+
113+-- | Extracts revision/schema pairs from @Versioned@ in reverse order.
114+type family AllVersions (vd :: Versioned) :: Revisions where
115+ AllVersions ('Versioned s ms) = AllVersions' ('Revisions s '[ '("initial", s) ]) ms
116+
117+type family AllVersions' (acc :: Revisions) (ms :: [Migration]) :: Revisions where
118+ AllVersions' acc '[] = acc
119+ AllVersions' ('Revisions tv rs) (m ': ms) =
120+ AllVersions' ('Revisions (Snd (ApplyMigration m tv)) (rs :++ '[(ApplyMigration m tv)])) ms
121+
122+type family TopVersion (rs :: Revisions) :: Schema where
123+ TopVersion ('Revisions s rs) = s
124+
125+type family SchemaPairs (rs :: Revisions) :: [(Revision, Schema)] where
126+ SchemaPairs ('Revisions s rs) = rs
77127
78128class MigrateSchema (a :: Schema) (b :: Schema) where
79129 migrate :: JsonRepr a -> JsonRepr b
80130
131+instance MigrateSchema a a where
132+ migrate = id
133+
81134data Action = AddKey Symbol Schema | Update Schema | DeleteKey Symbol
82135
83136data instance Sing (a :: Action) where
@@ -137,7 +190,7 @@ type VS =
137190 '[ 'Migration "test_revision"
138191 '[ 'Diff '[ 'PKey "foo" ] ('Update ('SchemaText '[])) ] ]
139192
140−jsonExample :: JsonRepr (TopVersion VS)
193+jsonExample :: JsonRepr (TopVersion (AllVersions VS))
141194jsonExample = ReprObject $
142195 FieldRepr (ReprText "foo")
143196 :& FieldRepr (ReprOptional (Just (ReprText "bar")))