@@ -5,7 +5,6 @@
55{-# language FlexibleInstances #-}
66{-# language MultiParamTypeClasses #-}
77{-# language NamedFieldPuns #-}
8−{-# language RecordWildCards #-}
98{-# language ScopedTypeVariables #-}
109{-# language StandaloneKindSignatures #-}
1110{-# language TupleSections #-}
@@ -21,6 +20,7 @@ module Rel8.Table.These
2120 , isThisTable, isThatTable, isThoseTable
2221 , hasHereTable, hasThereTable
2322 , justHereTable, justThereTable
23+ , aggregateTheseTable
2424 , nameTheseTable
2525 )
2626where
@@ -33,19 +33,17 @@ import Data.Kind ( Type )
3333import Prelude hiding ( undefined )
3434
3535-- rel8
36+import Rel8.Aggregate ( Aggregate )
3637import Rel8.Expr ( Expr )
3738import Rel8.Expr.Bool ( (&&.), not_ )
3839import Rel8.Expr.Null ( isNonNull )
39−import Rel8.Schema.Context.Nullify
40− ( Nullifiable
41− , encodeTag, decodeTag
42− , nullifier, unnullifier
43− )
40+import Rel8.Schema.Context.Nullify ( Nullifiable, nullifier, unnullifier )
4441import Rel8.Schema.Dict ( Dict( Dict ) )
4542import Rel8.Schema.HTable.Label ( hlabel, hunlabel )
4643import Rel8.Schema.HTable.Identity ( HIdentity(..) )
4744import Rel8.Schema.HTable.Nullify ( hnullify, hunnullify )
4845import Rel8.Schema.HTable.These ( HTheseTable(..) )
46+import qualified Rel8.Schema.Kind as K
4947import Rel8.Schema.Name ( Name )
5048import Rel8.Table
5149 ( Table, Columns, Context, fromColumns, toColumns
@@ -56,12 +54,12 @@ import Rel8.Table.Maybe
5654 ( MaybeTable(..)
5755 , maybeTable, justTable, nothingTable
5856 , isJustTable
57+ , aggregateMaybeTable
5958 , nameMaybeTable
6059 )
6160import Rel8.Table.Ord ( OrdTable, ordTable )
6261import Rel8.Table.Recontextualize ( Recontextualize )
6362import Rel8.Table.Serialize ( FromExprs, ToExprs, fromResult, toResult )
64−import Rel8.Table.Tag ( Tag(..) )
6563import Rel8.Table.Undefined ( undefined )
6664import Rel8.Type.Tag ( MaybeTag )
6765
@@ -80,32 +78,37 @@ import Data.These ( These )
8078--
8179-- @TheseTable@ is operationally the same as Haskell's 'These' type, but
8280-- adapted to work with Rel8.
83−type TheseTable :: Type -> Type -> Type
84−data TheseTable a b = TheseTable
85− { here :: MaybeTable a
86− , there :: MaybeTable b
81+type TheseTable :: K.Context -> Type -> Type -> Type
82+data TheseTable context a b = TheseTable
83+ { here :: MaybeTable context a
84+ , there :: MaybeTable context b
8785 }
8886 deriving stock Functor
8987
9088
91−instance Bifunctor TheseTable where
89+instance Bifunctor (TheseTable context) where
9290 bimap f g (TheseTable a b) = TheseTable (fmap f a) (fmap g b)
9391
9492
95−instance (Table Expr a, Semigroup a) => Apply (TheseTable a) where
93+instance (context ~ Expr, Table Expr a, Semigroup a) =>
94+ Apply (TheseTable context a)
95+ where
9696 fs <.> as = TheseTable
9797 { here = here fs <> here as
9898 , there = there fs <.> there as
9999 }
100100
101101
102−instance (Table Expr a, Semigroup a) => Applicative (TheseTable a)
102+instance (context ~ Expr, Table Expr a, Semigroup a) =>
103+ Applicative (TheseTable context a)
103104 where
104105 pure = thatTable
105106 (<*>) = (<.>)
106107
107108
108−instance (Table Expr a, Semigroup a) => Bind (TheseTable a) where
109+instance (context ~ Expr, Table Expr a, Semigroup a) =>
110+ Bind (TheseTable context a)
111+ where
109112 TheseTable here1 ma >>- f = case ma >>- f' of
110113 mtb -> TheseTable
111114 { here = maybeTable here1 ((here1 <>) . fst) mtb
@@ -116,12 +119,14 @@ instance (Table Expr a, Semigroup a) => Bind (TheseTable a) where
116119 TheseTable here2 mb -> (here2,) <$> mb
117120
118121
119−instance (Table Expr a, Semigroup a) => Monad (TheseTable a) where
122+instance (context ~ Expr, Table Expr a, Semigroup a) =>
123+ Monad (TheseTable context a)
124+ where
120125 (>>=) = (>>-)
121126
122127
123−instance (Table Expr a, Table Expr b, Semigroup a, Semigroup b) =>
124− Semigroup (TheseTable a b)
128+instance (context ~ Expr, Table Expr a, Table Expr b, Semigroup a, Semigroup b) =>
129+ Semigroup (TheseTable context a b)
125130 where
126131 a <> b = TheseTable
127132 { here = here a <> here b
@@ -131,67 +136,61 @@ instance (Table Expr a, Table Expr b, Semigroup a, Semigroup b) =>
131136
132137instance
133138 ( Table context a, Table context b
134− , Nullifiable context
139+ , Nullifiable context, context ~ context'
135140 )
136− => Table context (TheseTable a b)
141+ => Table context' (TheseTable context a b)
137142 where
138− type Columns (TheseTable a b) = HTheseTable (Columns a) (Columns b)
139− type Context (TheseTable a b) = Context a
143+ type Columns (TheseTable context a b) = HTheseTable (Columns a) (Columns b)
144+ type Context (TheseTable context a b) = Context a
140145
141146 toColumns TheseTable {here, there} = HTheseTable
142− { hhereTag = hlabel $ HType $ encodeTag (toHereTag (tag here))
147+ { hhereTag = hlabel (HIdentity (tag here))
143148 , hhere =
144149 hlabel $ hnullify (nullifier (tag here) isNonNull) $ toColumns $
145150 just here
146− , hthereTag = hlabel $ HType $ encodeTag (toThereTag (tag there))
151+ , hthereTag = hlabel (HIdentity (tag there))
147152 , hthere =
148153 hlabel $ hnullify (nullifier (tag there) isNonNull) $ toColumns $
149154 just there
150155 }
151156
152157 fromColumns HTheseTable {hhereTag, hhere, hthereTag, hthere} = TheseTable
153− { here =
154− let
155− tag = decodeTag $ unHIdentity $ hunlabel hhereTag
156− in
157− MaybeTable
158− { tag
159− , just =
160− fromColumns $
161− runIdentity $
162− hunnullify (\a -> pure . unnullifier a) $
163− hunlabel
164− hhere
165− }
166− , there =
167− let
168− tag = decodeTag $ unHIdentity $ hunlabel hthereTag
169− in
170− MaybeTable
171− { tag
172− , just =
173− fromColumns $
174− runIdentity $
175− hunnullify (\a -> pure . unnullifier a) $
176− hunlabel
177− hthere
178− }
158+ { here = MaybeTable
159+ { tag = unHIdentity $ hunlabel hhereTag
160+ , just =
161+ fromColumns $
162+ runIdentity $
163+ hunnullify (\a -> pure . unnullifier a) $
164+ hunlabel
165+ hhere
166+ }
167+ , there = MaybeTable
168+ { tag = unHIdentity $ hunlabel hthereTag
169+ , just =
170+ fromColumns $
171+ runIdentity $
172+ hunnullify (\a -> pure . unnullifier a) $
173+ hunlabel
174+ hthere
175+ }
179176 }
180177
181−
182178 reify = liftA2 bimap reify reify
183179 unreify = liftA2 bimap unreify unreify
184180
185181
186182instance
187− ( Nullifiable from, Nullifiable to
183+ ( Nullifiable from, from ~ from'
184+ , Nullifiable to, to ~ to'
188185 , Recontextualize from to a1 b1
189186 , Recontextualize from to a2 b2
190187 )
191− => Recontextualize from to (TheseTable a1 a2) (TheseTable b1 b2)
188+ => Recontextualize from to (TheseTable from' a1 a2) (TheseTable to' b1 b2)
192189
193190
194−instance (EqTable a, EqTable b) => EqTable (TheseTable a b) where
191+instance (EqTable a, EqTable b, context ~ Expr) =>
192+ EqTable (TheseTable context a b)
193+ where
195194 eqTable = HTheseTable
196195 { hhereTag = hlabel (HType Dict)
197196 , hhere = hlabel (hnullify (\_ Dict -> Dict) (eqTable @a))
@@ -200,7 +199,9 @@ instance (EqTable a, EqTable b) => EqTable (TheseTable a b) where
200199 }
201200
202201
203−instance (OrdTable a, OrdTable b) => OrdTable (TheseTable a b) where
202+instance (OrdTable a, OrdTable b, context ~ Expr) =>
203+ OrdTable (TheseTable context a b)
204+ where
204205 ordTable = HTheseTable
205206 { hhereTag = hlabel (HType Dict)
206207 , hhere = hlabel (hnullify (\_ Dict -> Dict) (ordTable @a))
@@ -209,10 +210,11 @@ instance (OrdTable a, OrdTable b) => OrdTable (TheseTable a b) where
209210 }
210211
211212
212−type instance FromExprs (TheseTable a b) = These (FromExprs a) (FromExprs b)
213+type instance FromExprs (TheseTable _context a b) =
214+ These (FromExprs a) (FromExprs b)
213215
214216
215−instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ TheseTable exprs1 exprs2) =>
217+instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ TheseTable Expr exprs1 exprs2) =>
216218 ToExprs x (These a b)
217219 where
218220 fromResult =
@@ -223,81 +225,73 @@ instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ TheseTable exprs1 exprs2) =>
223225 bimap (toResult @exprs1) (toResult @exprs2)
224226
225227
226−toHereTag :: Tag "isJust" a -> Tag "hasHere" a
227−toHereTag Tag {..} = Tag {..}
228−
229−
230−toThereTag :: Tag "isJust" a -> Tag "hasThere" a
231−toThereTag Tag {..} = Tag {..}
232−
233−
234228-- | Test if a 'TheseTable' was constructed with 'thisTable'.
235229--
236230-- Corresponds to 'Data.These.Combinators.isThis'.
237−isThisTable :: TheseTable a b -> Expr Bool
231+isThisTable :: TheseTable Expr a b -> Expr Bool
238232isThisTable a = hasHereTable a &&. not_ (hasThereTable a)
239233
240234
241235-- | Test if a 'TheseTable' was constructed with 'thatTable'.
242236--
243237-- Corresponds to 'Data.These.Combinators.isThat'.
244−isThatTable :: TheseTable a b -> Expr Bool
238+isThatTable :: TheseTable Expr a b -> Expr Bool
245239isThatTable a = not_ (hasHereTable a) &&. hasThereTable a
246240
247241
248242-- | Test if a 'TheseTable' was constructed with 'thoseTable'.
249243--
250244-- Corresponds to 'Data.These.Combinators.isThese'.
251−isThoseTable :: TheseTable a b -> Expr Bool
245+isThoseTable :: TheseTable Expr a b -> Expr Bool
252246isThoseTable a = hasHereTable a &&. hasThereTable a
253247
254248
255249-- | Test if the @a@ side of @TheseTable a b@ is present.
256250--
257251-- Corresponds to 'Data.These.Combinators.hasHere'.
258−hasHereTable :: TheseTable a b -> Expr Bool
252+hasHereTable :: TheseTable Expr a b -> Expr Bool
259253hasHereTable TheseTable {here} = isJustTable here
260254
261255
262256-- | Test if the @b@ table of @TheseTable a b@ is present.
263257--
264258-- Corresponds to 'Data.These.Combinators.hasThere'.
265−hasThereTable :: TheseTable a b -> Expr Bool
259+hasThereTable :: TheseTable Expr a b -> Expr Bool
266260hasThereTable TheseTable {there} = isJustTable there
267261
268262
269263-- | Attempt to project out the @a@ table of a @TheseTable a b@.
270264--
271265-- Corresponds to 'Data.These.Combinators.justHere'.
272−justHereTable :: TheseTable a b -> MaybeTable a
266+justHereTable :: TheseTable context a b -> MaybeTable context a
273267justHereTable = here
274268
275269
276270-- | Attempt to project out the @b@ table of a @TheseTable a b@.
277271--
278272-- Corresponds to 'Data.These.Combinators.justThere'.
279−justThereTable :: TheseTable a b -> MaybeTable b
273+justThereTable :: TheseTable context a b -> MaybeTable context b
280274justThereTable = there
281275
282276
283277-- | Construct a @TheseTable@. Corresponds to 'This'.
284−thisTable :: Table Expr b => a -> TheseTable a b
278+thisTable :: Table Expr b => a -> TheseTable Expr a b
285279thisTable a = TheseTable (justTable a) nothingTable
286280
287281
288282-- | Construct a @TheseTable@. Corresponds to 'That'.
289−thatTable :: Table Expr a => b -> TheseTable a b
283+thatTable :: Table Expr a => b -> TheseTable Expr a b
290284thatTable b = TheseTable nothingTable (justTable b)
291285
292286
293287-- | Construct a @TheseTable@. Corresponds to 'These'.
294−thoseTable :: a -> b -> TheseTable a b
288+thoseTable :: a -> b -> TheseTable Expr a b
295289thoseTable a b = TheseTable (justTable a) (justTable b)
296290
297291
298292-- | Pattern match on a 'TheseTable'. Corresponds to 'these'.
299293theseTable :: Table Expr c
300− => (a -> c) -> (b -> c) -> (a -> b -> c) -> TheseTable a b -> c
294+ => (a -> c) -> (b -> c) -> (a -> b -> c) -> TheseTable Expr a b -> c
301295theseTable f g h TheseTable {here, there} =
302296 maybeTable
303297 (maybeTable undefined f here)
@@ -305,6 +299,19 @@ theseTable f g h TheseTable {here, there} =
305299 there
306300
307301
302+-- | Lift a pair of aggregating functions to operate on an 'TheseTable'.
303+-- @thisTable@s, @thatTable@s and @thoseTable@s are grouped separately.
304+aggregateTheseTable :: ()
305+ => (exprs -> aggregates)
306+ -> (exprs' -> aggregates')
307+ -> TheseTable Expr exprs exprs'
308+ -> TheseTable Aggregate aggregates aggregates'
309+aggregateTheseTable f g (TheseTable here there) = TheseTable
310+ { here = aggregateMaybeTable f here
311+ , there = aggregateMaybeTable g there
312+ }
313+
314+
308315-- | Construct a 'TheseTable' in the 'Name' context. This can be useful if you
309316-- have a 'TheseTable' that you are storing in a table and need to construct a
310317-- 'TableSchema'.
@@ -317,7 +324,7 @@ nameTheseTable :: ()
317324 -- ^ Names of the columns in the @a@ table.
318325 -> b
319326 -- ^ Names of the columns in the @b@ table.
320− -> TheseTable a b
327+ -> TheseTable Name a b
321328nameTheseTable here there a b =
322329 TheseTable
323330 { here = nameMaybeTable here a