1{-# language AllowAmbiguousTypes #-}
2{-# language DataKinds #-}
3{-# language DefaultSignatures #-}
4{-# language DisambiguateRecordFields #-}
5{-# language FlexibleContexts #-}
6{-# language FlexibleInstances #-}
7{-# language FunctionalDependencies #-}
8{-# language LambdaCase #-}
9{-# language NamedFieldPuns #-}
10{-# language ScopedTypeVariables #-}
11{-# language StandaloneKindSignatures #-}
12{-# language TypeApplications #-}
13{-# language TypeFamilies #-}
14{-# language TypeOperators #-}
15{-# language UndecidableInstances #-}
19 ( Columns, Context, toColumns, fromColumns
20 , Unreify, reify, unreify, coherence, congruence
23 , TTable, TColumns, TContext, TUnreify
28import Data.Functor ( ($>) )
29import Data.Functor.Identity ( Identity( Identity ) )
30import Data.Kind ( Constraint, Type )
31import Data.List.NonEmpty ( NonEmpty )
32import Data.Proxy ( Proxy( Proxy ) )
33import Data.Type.Equality ( (:~:)( Refl ) )
34import GHC.Generics ( Generic, Rep, from, to )
35import Prelude hiding ( null )
38import Rel8.FCF ( Eval, Exp )
39import Rel8.Kind.Algebra
40 ( SAlgebra( SSum, SProduct )
41 , KnownAlgebra, algebraSing
43import Rel8.Generic.Coherence ( GCoherent, gcoherence, gcongruence )
44import Rel8.Generic.Map ( GMap, GMappable, gmap, gunmap )
45import Rel8.Generic.Table
46 ( GGTable, GGColumns, GGContext, ggfromColumns, ggtoColumns
49import Rel8.Generic.Record ( Record(..) )
50import Rel8.Generic.Reify ( ARep )
51import Rel8.Schema.HTable ( HTable )
52import Rel8.Schema.HTable.Either ( HEitherTable(..) )
53import Rel8.Schema.HTable.Identity ( HIdentity(..), HType )
54import Rel8.Schema.HTable.Label ( hlabel, hrelabel, hunlabel )
55import Rel8.Schema.HTable.List ( HListTable )
56import Rel8.Schema.HTable.Maybe ( HMaybeTable(..) )
57import Rel8.Schema.HTable.NonEmpty ( HNonEmptyTable )
58import Rel8.Schema.HTable.Nullify ( hnulls, hnullify, hunnullify )
59import Rel8.Schema.HTable.These ( HTheseTable(..) )
60import Rel8.Schema.HTable.Vectorize ( hvectorize, hunvectorize )
61import qualified Rel8.Schema.Kind as K
62import Rel8.Schema.Null ( Sql )
63import Rel8.Schema.Reify
64 ( Reify, Col( Reify ), hreify, hunreify
68import Rel8.Schema.Result
71 , null, nullifier, unnullifier
72 , vectorizer, unvectorizer
74import Rel8.Schema.Spec ( KnownSpec )
75import Rel8.Type ( DBType )
76import Rel8.Type.Tag ( EitherTag( IsLeft, IsRight ), MaybeTag( IsJust ) )
79import Data.These ( These( This, That, These ) )
80import Data.These.Combinators ( justHere, justThere )
83-- | @Table@s are one of the foundational elements of Rel8, and describe data
84-- types that have a finite number of columns. Each of these columns contains
85-- data under a shared context, and contexts describe how to interpret the
86-- metadata about a column to a particular Haskell type. In Rel8, we have
87-- contexts for expressions (the 'Rel8.Expr' context), aggregations (the
88-- 'Rel8.Aggregate' context), insert values (the 'Rel8.Insert' contex), among
91-- In typical usage of Rel8 you don't need to derive instances of 'Table'
92-- yourself, as anything that's an instance of 'Rel8.Rel8able' is always a
94type Table :: K.Context -> Type -> Constraint
95class (HTable (Columns a), context ~ Context a) => Table context a | a -> context where
96 -- | The 'HTable' functor that describes the schema of this table.
97 type Columns a :: K.HTable
99 -- | The common context that all columns use as an interpretation.
100 type Context a :: K.Context
102 type Unreify a :: Type
104 toColumns :: a -> Columns a (Col context)
105 fromColumns :: Columns a (Col context) -> a
107 reify :: context :~: Reify ctx -> Unreify a -> a
108 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)
113 type Columns a = Eval (GGColumns (GAlgebra (Rep (Record a))) TColumns (Rep (Record a)))
114 type Context a = Eval (GGContext (GAlgebra (Rep (Record a))) TContext (Rep (Record a)))
115 type Unreify a = DefaultUnreify a
119 , KnownAlgebra (GAlgebra (Rep (Record a)))
120 , Eval (GGTable (GAlgebra (Rep (Record a))) (TTable context) TColumns (Col context) (Rep (Record a)))
121 , Columns a ~ Eval (GGColumns (GAlgebra (Rep (Record a))) TColumns (Rep (Record a)))
122 , Context a ~ Eval (GGContext (GAlgebra (Rep (Record a))) TContext (Rep (Record a)))
124 => a -> Columns a (Col context)
127 @(GAlgebra (Rep (Record a)))
136 default fromColumns ::
138 , KnownAlgebra (GAlgebra (Rep (Record a)))
139 , Eval (GGTable (GAlgebra (Rep (Record a))) (TTable context) TColumns (Col context) (Rep (Record a)))
140 , Columns a ~ Eval (GGColumns (GAlgebra (Rep (Record a))) TColumns (Rep (Record a)))
141 , Context a ~ Eval (GGContext (GAlgebra (Rep (Record a))) TContext (Rep (Record a)))
143 => Columns a (Col context) -> a
148 @(GAlgebra (Rep (Record a)))
157 , Generic (Record (Unreify a))
158 , GMappable (TTable context) (Rep (Record a))
159 , Rep (Record (Unreify a)) ~ GMap TUnreify (Rep (Record a))
161 => context :~: Reify ctx -> Unreify a -> a
165 gunmap @(TTable context) (Proxy @TUnreify) (reify Refl) .
171 , Generic (Record (Unreify a))
172 , GMappable (TTable context) (Rep (Record a))
173 , Rep (Record (Unreify a)) ~ GMap TUnreify (Rep (Record a))
175 => context :~: Reify ctx -> a -> Unreify a
179 gmap @(TTable context) (Proxy @TUnreify) (unreify Refl) .
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))
190 => context :~: Reify ctx -> NotResult ctx -> Context (Unreify a) :~: ctx
191 coherence = case algebraSing @(GAlgebra (Rep (Record a))) of
193 SProduct -> \proof abstract ->
199 (\(_ :: _proxy x) -> coherence @context @x proof abstract)
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))
209 => context :~: Reify ctx -> NotResult ctx -> Columns a :~: Columns (Unreify a)
210 congruence = case algebraSing @(GAlgebra (Rep (Record a))) of
212 SProduct -> \proof abstract ->
218 (\(_ :: _proxy x) -> congruence @context @x proof abstract)
221data TTable :: K.Context -> Type -> Exp Constraint
222type instance Eval (TTable context a) = Table context a
225data TColumns :: Type -> Exp K.HTable
226type instance Eval (TColumns a) = Columns a
229data TContext :: Type -> Exp K.Context
230type instance Eval (TContext a) = Context a
233data TUnreify :: Type -> Exp Type
234type instance Eval (TUnreify a) = Unreify a
237type DefaultUnreify :: Type -> Type
238type family DefaultUnreify a where
239 DefaultUnreify (t a b c d e f g) =
240 t (Unreify a) (Unreify b) (Unreify c) (Unreify d) (Unreify e) (Unreify f) (Unreify g)
241 DefaultUnreify (t a b c d e f) =
242 t (Unreify a) (Unreify b) (Unreify c) (Unreify d) (Unreify e) (Unreify f)
243 DefaultUnreify (t a b c d e) =
244 t (Unreify a) (Unreify b) (Unreify c) (Unreify d) (Unreify e)
245 DefaultUnreify (t a b c d) =
246 t (Unreify a) (Unreify b) (Unreify c) (Unreify d)
247 DefaultUnreify (t a b c) = t (Unreify a) (Unreify b) (Unreify c)
248 DefaultUnreify (t a b) = t (Unreify a) (Unreify b)
249 DefaultUnreify (t a) = t (Unreify a)
250 DefaultUnreify a = ARep (GMap TUnreify (Rep a))
253-- | Any 'HTable' is also a 'Table'.
254instance HTable t => Table context (t (Col context)) where
255 type Columns (t (Col context)) = t
256 type Context (t (Col context)) = context
257 type Unreify (t (Col context)) = t (Col (UnwrapReify context))
263 unreify Refl = hunreify
264 coherence Refl _ = Refl
265 congruence Refl _ = Refl
268-- | Any context is trivially a table.
269instance KnownSpec spec => Table context (Col context spec) where
270 type Columns (Col context spec) = HIdentity spec
271 type Context (Col context spec) = context
272 type Unreify (Col context spec) = Col (UnwrapReify context) spec
274 toColumns = HIdentity
275 fromColumns = unHIdentity
278 unreify Refl (Reify a) = a
279 coherence Refl _ = Refl
280 congruence Refl _ = Refl
283instance Sql DBType a => Table Result (Identity a) where
284 type Columns (Identity a) = HType a
285 type Context (Identity a) = Result
287 toColumns (Identity a) = HType (R a)
288 fromColumns (HType (R a)) = Identity a
293 congruence = notReify
296instance (context ~ Result, Table context a, Table context b) =>
297 Table context (Either a b)
299 type Columns (Either a b) = HEitherTable (Columns a) (Columns b)
300 type Context (Either a b) = Context a
303 Left table -> HEitherTable
304 { htag = hlabel (HType (R IsLeft))
305 , hleft = hlabel (hnullify nullifier (toColumns table))
306 , hright = hlabel (hnulls (const null))
308 Right table -> HEitherTable
309 { htag = hlabel (HType (R IsRight))
310 , hleft = hlabel (hnulls (const null))
311 , hright = hlabel (hnullify nullifier (toColumns table))
314 fromColumns HEitherTable {htag, hleft, hright} = case hunlabel htag of
315 HType (R tag) -> case tag of
316 IsLeft -> maybe err (Left . fromColumns) $ hunnullify unnullifier (hunlabel hleft)
317 IsRight -> maybe err (Right . fromColumns) $ hunnullify unnullifier (hunlabel hright)
319 err = error "Either.fromColumns: mismatch between tag and data"
322 congruence = notReify
325instance (context ~ Result, Table context a) => Table context [a] where
326 type Columns [a] = HListTable (Columns a)
327 type Context [a] = Context a
329 toColumns = hvectorize vectorizer . fmap toColumns
330 fromColumns = fmap fromColumns . hunvectorize unvectorizer
333 congruence = notReify
336instance (context ~ Result, Table context a) => Table context (Maybe a) where
337 type Columns (Maybe a) = HMaybeTable (Columns a)
338 type Context (Maybe a) = Context a
341 Nothing -> HMaybeTable
342 { htag = hlabel (HIdentity (R Nothing))
343 , hjust = hlabel (hnulls (const null))
345 Just table -> HMaybeTable
346 { htag = hlabel (HIdentity (R (Just IsJust)))
347 , hjust = hlabel (hnullify nullifier (toColumns table))
350 fromColumns HMaybeTable {htag, hjust} = case hunlabel htag of
351 HType (R tag) -> tag $>
352 case hunnullify unnullifier (hunlabel hjust) of
353 Nothing -> error "Maybe.fromColumns: mismatch between tag and data"
354 Just just -> fromColumns just
357 congruence = notReify
360instance (context ~ Result, Table context a) => Table context (NonEmpty a)
362 type Columns (NonEmpty a) = HNonEmptyTable (Columns a)
363 type Context (NonEmpty a) = Context a
365 toColumns = hvectorize vectorizer . fmap toColumns
366 fromColumns = fmap fromColumns . hunvectorize unvectorizer
369 congruence = notReify
372instance (context ~ Result, Table context a, Table context b) =>
373 Table context (These a b)
375 type Columns (These a b) = HTheseTable (Columns a) (Columns b)
376 type Context (These a b) = Context a
378 toColumns tables = HTheseTable
379 { hhereTag = hrelabel hhereTag
380 , hhere = hrelabel (toColumns hhere)
381 , hthereTag = hrelabel hthereTag
382 , hthere = hrelabel (toColumns hthere)
388 } = toColumns (justHere tables)
392 } = toColumns (justThere tables)
394 fromColumns HTheseTable {hhereTag, hhere, hthereTag, hthere} =
395 case (fromColumns mhere, fromColumns mthere) of
396 (Just a, Nothing) -> This (fromColumns a)
397 (Nothing, Just b) -> That (fromColumns b)
398 (Just a, Just b) -> These (fromColumns a) (fromColumns b)
399 _ -> error "These.fromColumns: mismatch between tags and data"
402 { htag = hrelabel hhereTag
403 , hjust = hrelabel hhere
406 { htag = hrelabel hthereTag
407 , hjust = hrelabel hthere
411 congruence = notReify
414instance (Table context a, Table context b) => Table context (a, b)
418 ( Table context a, Table context b, Table context c
420 => Table context (a, b, c)
424 ( Table context a, Table context b, Table context c, Table context d
426 => Table context (a, b, c, d)
430 ( Table context a, Table context b, Table context c, Table context d
433 => Table context (a, b, c, d, e)
437 ( Table context a, Table context b, Table context c, Table context d
438 , Table context e, Table context f
440 => Table context (a, b, c, d, e, f)
444 ( Table context a, Table context b, Table context c, Table context d
445 , Table context e, Table context f, Table context g
447 => Table context (a, b, c, d, e, f, g)
450type Congruent :: Type -> Type -> Constraint
451class Columns a ~ Columns b => Congruent a b
452instance Columns a ~ Columns b => Congruent a b
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list