@@ -15,7 +15,10 @@
1515{-# language UndecidableInstances #-}
1616
1717module Rel8.Table
18− ( Table (Columns, Context, Unreify, toColumns, fromColumns, reify, unreify)
18+ ( Table
19+ ( Columns, Context, toColumns, fromColumns
20+ , Unreify, reify, unreify, coherence, congruence
21+ )
1922 , Congruent
2023 , TTable, TColumns, TContext, TUnreify
2124 )
@@ -33,7 +36,11 @@ import Prelude hiding ( null )
3336
3437-- rel8
3538import Rel8.FCF ( Eval, Exp )
36−import Rel8.Kind.Algebra ( KnownAlgebra )
39+import Rel8.Kind.Algebra
40+ ( SAlgebra( SSum, SProduct )
41+ , KnownAlgebra, algebraSing
42+ )
43+import Rel8.Generic.Coherence ( GCoherent, gcoherence, gcongruence )
3744import Rel8.Generic.Map ( GMap, GMappable, gmap, gunmap )
3845import Rel8.Generic.Table
3946 ( GGTable, GGColumns, GGContext, ggfromColumns, ggtoColumns
@@ -60,6 +67,7 @@ import Rel8.Schema.Reify
6067 )
6168import Rel8.Schema.Result
6269 ( Col( R ), Result
70+ , NotResult
6371 , null, nullifier, unnullifier
6472 , vectorizer, unvectorizer
6573 )
@@ -98,6 +106,9 @@ class (HTable (Columns a), context ~ Context a) => Table context a | a -> contex
98106
99107 reify :: context :~: Reify ctx -> Unreify a -> a
100108 unreify :: context :~: Reify ctx -> a -> Unreify a
109+ coherence :: context :~: Reify ctx -> NotResult ctx -> Context (Unreify a) :~: ctx
110+ congruence :: context :~: Reify ctx -> NotResult ctx -> Columns a :~: Columns (Unreify a)
111+
101112
102113 type Columns a = Eval (GGColumns (GAlgebra (Rep (Record a))) TColumns (Rep (Record a)))
103114 type Context a = Eval (GGContext (GAlgebra (Rep (Record a))) TContext (Rep (Record a)))
@@ -169,6 +180,43 @@ class (HTable (Columns a), context ~ Context a) => Table context a | a -> contex
169180 from .
170181 Record
171182
183+ default coherence ::
184+ ( KnownAlgebra (GAlgebra (Rep (Record a)))
185+ , GCoherent (TTable context) (Rep (Record a))
186+ , Context a ~ Eval (GGContext (GAlgebra (Rep (Record a))) TContext (Rep (Record a)))
187+ , Context (Unreify a) ~ Eval (GGContext (GAlgebra (Rep (Record a))) TContext (Rep (Record (Unreify a))))
188+ , Rep (Record (Unreify a)) ~ GMap TUnreify (Rep (Record a))
189+ )
190+ => context :~: Reify ctx -> NotResult ctx -> Context (Unreify a) :~: ctx
191+ coherence = case algebraSing @(GAlgebra (Rep (Record a))) of
192+ SSum -> notReify
193+ SProduct -> \proof abstract ->
194+ gcoherence
195+ @(TTable context)
196+ @(Rep (Record a))
197+ (Proxy @TContext)
198+ (Proxy @TUnreify)
199+ (\(_ :: _proxy x) -> coherence @context @x proof abstract)
200+
201+ default congruence ::
202+ ( KnownAlgebra (GAlgebra (Rep (Record a)))
203+ , GCoherent (TTable context) (Rep (Record a))
204+ , Context a ~ Eval (GGContext (GAlgebra (Rep (Record a))) TContext (Rep (Record a)))
205+ , Columns a ~ Eval (GGColumns (GAlgebra (Rep (Record a))) TColumns (Rep (Record a)))
206+ , Columns (Unreify a) ~ Eval (GGColumns (GAlgebra (Rep (Record a))) TColumns (Rep (Record (Unreify a))))
207+ , Rep (Record (Unreify a)) ~ GMap TUnreify (Rep (Record a))
208+ )
209+ => context :~: Reify ctx -> NotResult ctx -> Columns a :~: Columns (Unreify a)
210+ congruence = case algebraSing @(GAlgebra (Rep (Record a))) of
211+ SSum -> notReify
212+ SProduct -> \proof abstract ->
213+ gcongruence
214+ @(TTable context)
215+ @(Rep (Record a))
216+ (Proxy @TColumns)
217+ (Proxy @TUnreify)
218+ (\(_ :: _proxy x) -> congruence @context @x proof abstract)
219+
172220
173221data TTable :: K.Context -> Type -> Exp Constraint
174222type instance Eval (TTable context a) = Table context a
@@ -213,6 +261,8 @@ instance HTable t => Table context (t (Col context)) where
213261
214262 reify Refl = hreify
215263 unreify Refl = hunreify
264+ coherence Refl _ = Refl
265+ congruence Refl _ = Refl
216266
217267
218268-- | Any context is trivially a table.
@@ -226,6 +276,8 @@ instance KnownSpec spec => Table context (Col context spec) where
226276
227277 reify Refl = Reify
228278 unreify Refl (Reify a) = a
279+ coherence Refl _ = Refl
280+ congruence Refl _ = Refl
229281
230282
231283instance Sql DBType a => Table Result (Identity a) where
@@ -237,11 +289,15 @@ instance Sql DBType a => Table Result (Identity a) where
237289
238290 reify = notReify
239291 unreify = notReify
292+ coherence = notReify
293+ congruence = notReify
240294
241295
242−instance (Table Result a, Table Result b) => Table Result (Either a b) where
296+instance (context ~ Result, Table context a, Table context b) =>
297+ Table context (Either a b)
298+ where
243299 type Columns (Either a b) = HEitherTable (Columns a) (Columns b)
244− type Context (Either a b) = Result
300+ type Context (Either a b) = Context a
245301
246302 toColumns = \case
247303 Left table -> HEitherTable
@@ -262,18 +318,24 @@ instance (Table Result a, Table Result b) => Table Result (Either a b) where
262318 where
263319 err = error "Either.fromColumns: mismatch between tag and data"
264320
321+ coherence = notReify
322+ congruence = notReify
265323
266−instance Table Result a => Table Result [a] where
324+
325+instance (context ~ Result, Table context a) => Table context [a] where
267326 type Columns [a] = HListTable (Columns a)
268− type Context [a] = Result
327+ type Context [a] = Context a
269328
270329 toColumns = hvectorize vectorizer . fmap toColumns
271330 fromColumns = fmap fromColumns . hunvectorize unvectorizer
272331
332+ coherence = notReify
333+ congruence = notReify
334+
273335
274−instance Table Result a => Table Result (Maybe a) where
336+instance (context ~ Result, Table context a) => Table context (Maybe a) where
275337 type Columns (Maybe a) = HMaybeTable (Columns a)
276− type Context (Maybe a) = Result
338+ type Context (Maybe a) = Context a
277339
278340 toColumns = \case
279341 Nothing -> HMaybeTable
@@ -291,18 +353,27 @@ instance Table Result a => Table Result (Maybe a) where
291353 Nothing -> error "Maybe.fromColumns: mismatch between tag and data"
292354 Just just -> fromColumns just
293355
356+ coherence = notReify
357+ congruence = notReify
294358
295−instance Table Result a => Table Result (NonEmpty a) where
359+
360+instance (context ~ Result, Table context a) => Table context (NonEmpty a)
361+ where
296362 type Columns (NonEmpty a) = HNonEmptyTable (Columns a)
297− type Context (NonEmpty a) = Result
363+ type Context (NonEmpty a) = Context a
298364
299365 toColumns = hvectorize vectorizer . fmap toColumns
300366 fromColumns = fmap fromColumns . hunvectorize unvectorizer
301367
368+ coherence = notReify
369+ congruence = notReify
370+
302371
303−instance (Table Result a, Table Result b) => Table Result (These a b) where
372+instance (context ~ Result, Table context a, Table context b) =>
373+ Table context (These a b)
374+ where
304375 type Columns (These a b) = HTheseTable (Columns a) (Columns b)
305− type Context (These a b) = Result
376+ type Context (These a b) = Context a
306377
307378 toColumns tables = HTheseTable
308379 { hhereTag = hrelabel hhereTag
@@ -336,9 +407,11 @@ instance (Table Result a, Table Result b) => Table Result (These a b) where
336407 , hjust = hrelabel hthere
337408 }
338409
410+ coherence = notReify
411+ congruence = notReify
412+
339413
340−instance (Table context a, Table context b)
341− => Table context (a, b)
414+instance (Table context a, Table context b) => Table context (a, b)
342415
343416
344417instance