on f47423e help sign in
rel8/src/Rel8/Table.hs
208 lines 5.7 kB history raw
1{-# language AllowAmbiguousTypes #-}
2{-# language DataKinds #-}
3{-# language DefaultSignatures #-}
4{-# language FlexibleContexts #-}
5{-# language FlexibleInstances #-}
6{-# language FunctionalDependencies #-}
7{-# language ScopedTypeVariables #-}
8{-# language StandaloneKindSignatures #-}
9{-# language TypeApplications #-}
10{-# language TypeFamilies #-}
11{-# language UndecidableInstances #-}
13module Rel8.Table
14 ( Table
15 ( Columns, Context, fromColumns, toColumns
16 , FromExprs, fromResult, toResult
17 , Transpose
18 )
19 , Congruent
20 , TTable, TColumns, TContext, TFromExprs
21 )
22where
24-- base
25import Data.Kind ( Constraint, Type )
26import GHC.Generics ( Generic, Rep, from, to )
27import Prelude hiding ( null )
29-- rel8
30import Rel8.FCF ( Eval, Exp )
31import Rel8.Generic.Map ( GMap, Map )
32import Rel8.Generic.Table.Record
33 ( GTable, GColumns, GContext
34 , gfromColumns, gtoColumns, gfromResult, gtoResult
35 )
36import Rel8.Generic.Record ( Record(..) )
37import Rel8.Schema.HTable ( HTable )
38import qualified Rel8.Schema.Kind as K
39import Rel8.Schema.Result ( Result )
42-- | @Table@s are one of the foundational elements of Rel8, and describe data
43-- types that have a finite number of columns. Each of these columns contains
44-- data under a shared context, and contexts describe how to interpret the
45-- metadata about a column to a particular Haskell type. In Rel8, we have
46-- contexts for expressions (the 'Rel8.Expr' context), aggregations (the
47-- 'Rel8.Aggregate' context), insert values (the 'Rel8.Insert' contex), among
48-- others.
49--
50-- In typical usage of Rel8 you don't need to derive instances of 'Table'
51-- yourself, as anything that's an instance of 'Rel8.Rel8able' is always a
52-- 'Table'.
53type Table :: K.Context -> Type -> Constraint
54class
55 ( HTable (Columns a)
56 , context ~ Context a
57 , a ~ Transpose context a
58 )
59 => Table context a | a -> context
60 where
61 -- | The 'HTable' functor that describes the schema of this table.
62 type Columns a :: K.HTable
64 -- | The common context that all columns use as an interpretation.
65 type Context a :: K.Context
67 -- | The @FromExprs@ type family maps a type in the @Expr@ context to the
68 -- corresponding Haskell type.
69 type FromExprs a :: Type
71 type Transpose (context' :: K.Context) a :: Type
74 toColumns :: a -> Columns a context
75 fromColumns :: Columns a context -> a
77 fromResult :: Columns a Result -> FromExprs a
78 toResult :: FromExprs a -> Columns a Result
80 type Columns a = GColumns TColumns (Rep (Record a))
81 type Context a = GContext TContext (Rep (Record a))
82 type FromExprs a = Map TFromExprs a
83 type Transpose context a = Map (TTranspose context) a
85 default toColumns ::
86 ( Generic (Record a)
87 , GTable (TTable context) TColumns TFromExprs (Rep (Record a))
88 , Columns a ~ GColumns TColumns (Rep (Record a))
89 )
90 => a -> Columns a context
91 toColumns =
92 gtoColumns
93 @(TTable context)
94 @TColumns
95 @TFromExprs
96 toColumns .
97 from .
98 Record
100 default fromColumns ::
101 ( Generic (Record a)
102 , GTable (TTable context) TColumns TFromExprs (Rep (Record a))
103 , Columns a ~ GColumns TColumns (Rep (Record a))
104 )
105 => Columns a context -> a
106 fromColumns =
107 unrecord .
108 to .
109 gfromColumns
110 @(TTable context)
111 @TColumns
112 @TFromExprs
113 fromColumns
115 default toResult ::
116 ( Generic (Record (FromExprs a))
117 , GTable (TTable context) TColumns TFromExprs (Rep (Record a))
118 , Columns a ~ GColumns TColumns (Rep (Record a))
119 , Rep (Record (FromExprs a)) ~ GMap TFromExprs (Rep (Record a))
120 )
121 => FromExprs a -> Columns a Result
122 toResult =
123 gtoResult
124 @(TTable context)
125 @TColumns
126 @TFromExprs
127 @(Rep (Record a))
128 (\(_ :: proxy x) -> toResult @(Context x) @x) .
129 from .
130 Record
132 default fromResult ::
133 ( Generic (Record (FromExprs a))
134 , GTable (TTable context) TColumns TFromExprs (Rep (Record a))
135 , Columns a ~ GColumns TColumns (Rep (Record a))
136 , Rep (Record (FromExprs a)) ~ GMap TFromExprs (Rep (Record a))
137 )
138 => Columns a Result -> FromExprs a
139 fromResult =
140 unrecord .
141 to .
142 gfromResult
143 @(TTable context)
144 @TColumns
145 @TFromExprs
146 @(Rep (Record a))
147 (\(_ :: proxy x) -> fromResult @(Context x) @x)
150data TTable :: K.Context -> Type -> Exp Constraint
151type instance Eval (TTable context a) = Table context a
154data TColumns :: Type -> Exp K.HTable
155type instance Eval (TColumns a) = Columns a
158data TContext :: Type -> Exp K.Context
159type instance Eval (TContext a) = Context a
162data TFromExprs :: Type -> Exp Type
163type instance Eval (TFromExprs a) = FromExprs a
166data TTranspose :: K.Context -> Type -> Exp Type
167type instance Eval (TTranspose context a) = Transpose context a
170instance (Table context a, Table context b) => Table context (a, b)
173instance
174 ( Table context a, Table context b, Table context c
175 )
176 => Table context (a, b, c)
179instance
180 ( Table context a, Table context b, Table context c, Table context d
181 )
182 => Table context (a, b, c, d)
185instance
186 ( Table context a, Table context b, Table context c, Table context d
187 , Table context e
188 )
189 => Table context (a, b, c, d, e)
192instance
193 ( Table context a, Table context b, Table context c, Table context d
194 , Table context e, Table context f
195 )
196 => Table context (a, b, c, d, e, f)
199instance
200 ( Table context a, Table context b, Table context c, Table context d
201 , Table context e, Table context f, Table context g
202 )
203 => Table context (a, b, c, d, e, f, g)
206type Congruent :: Type -> Type -> Constraint
207class Columns a ~ Columns b => Congruent a b
208instance Columns a ~ Columns b => Congruent a b