@@ -5,7 +5,6 @@
5{-# language FlexibleInstances #-}
5{-# language FlexibleInstances #-}
6{-# language MultiParamTypeClasses #-}
6{-# language MultiParamTypeClasses #-}
7{-# language NamedFieldPuns #-}
7{-# language NamedFieldPuns #-}
8−{-# language RecordWildCards #-}
9{-# language ScopedTypeVariables #-}
8{-# language ScopedTypeVariables #-}
10{-# language StandaloneKindSignatures #-}
9{-# language StandaloneKindSignatures #-}
11{-# language TupleSections #-}
10{-# language TupleSections #-}
@@ -21,6 +20,7 @@ module Rel8.Table.These
21 , isThisTable, isThatTable, isThoseTable
20 , isThisTable, isThatTable, isThoseTable
22 , hasHereTable, hasThereTable
21 , hasHereTable, hasThereTable
23 , justHereTable, justThereTable
22 , justHereTable, justThereTable
23+ , aggregateTheseTable
24 , nameTheseTable
24 , nameTheseTable
@@ -33,19 +33,17 @@ import Data.Kind ( Type )
33import Prelude hiding ( undefined )
33import Prelude hiding ( undefined )
36+import Rel8.Aggregate ( Aggregate )
36import Rel8.Expr ( Expr )
37import Rel8.Expr ( Expr )
37import Rel8.Expr.Bool ( (&&.), not_ )
38import Rel8.Expr.Bool ( (&&.), not_ )
38import Rel8.Expr.Null ( isNonNull )
39import Rel8.Expr.Null ( isNonNull )
39−import Rel8.Schema.Context.Nullify
40+import Rel8.Schema.Context.Nullify ( Nullifiable, nullifier, unnullifier )
41− , encodeTag, decodeTag
42− , nullifier, unnullifier
44import Rel8.Schema.Dict ( Dict( Dict ) )
41import Rel8.Schema.Dict ( Dict( Dict ) )
45import Rel8.Schema.HTable.Label ( hlabel, hunlabel )
42import Rel8.Schema.HTable.Label ( hlabel, hunlabel )
46import Rel8.Schema.HTable.Identity ( HIdentity(..) )
43import Rel8.Schema.HTable.Identity ( HIdentity(..) )
47import Rel8.Schema.HTable.Nullify ( hnullify, hunnullify )
44import Rel8.Schema.HTable.Nullify ( hnullify, hunnullify )
48import Rel8.Schema.HTable.These ( HTheseTable(..) )
45import Rel8.Schema.HTable.These ( HTheseTable(..) )
46+import qualified Rel8.Schema.Kind as K
49import Rel8.Schema.Name ( Name )
47import Rel8.Schema.Name ( Name )
50import Rel8.Table
48import Rel8.Table
51 ( Table, Columns, Context, fromColumns, toColumns
49 ( Table, Columns, Context, fromColumns, toColumns
@@ -56,12 +54,12 @@ import Rel8.Table.Maybe
56 ( MaybeTable(..)
54 ( MaybeTable(..)
57 , maybeTable, justTable, nothingTable
55 , maybeTable, justTable, nothingTable
58 , isJustTable
56 , isJustTable
57+ , aggregateMaybeTable
59 , nameMaybeTable
58 , nameMaybeTable
61import Rel8.Table.Ord ( OrdTable, ordTable )
60import Rel8.Table.Ord ( OrdTable, ordTable )
62import Rel8.Table.Recontextualize ( Recontextualize )
61import Rel8.Table.Recontextualize ( Recontextualize )
63import Rel8.Table.Serialize ( FromExprs, ToExprs, fromResult, toResult )
62import Rel8.Table.Serialize ( FromExprs, ToExprs, fromResult, toResult )
64−import Rel8.Table.Tag ( Tag(..) )
65import Rel8.Table.Undefined ( undefined )
63import Rel8.Table.Undefined ( undefined )
66import Rel8.Type.Tag ( MaybeTag )
64import Rel8.Type.Tag ( MaybeTag )
@@ -80,32 +78,37 @@ import Data.These ( These )
81-- @TheseTable@ is operationally the same as Haskell's 'These' type, but
79-- @TheseTable@ is operationally the same as Haskell's 'These' type, but
82-- adapted to work with Rel8.
80-- adapted to work with Rel8.
83−type TheseTable :: Type -> Type -> Type
81+type TheseTable :: K.Context -> Type -> Type -> Type
84−data TheseTable a b = TheseTable
82+data TheseTable context a b = TheseTable
85− { here :: MaybeTable a
83+ { here :: MaybeTable context a
86− , there :: MaybeTable b
84+ , there :: MaybeTable context b
88 deriving stock Functor
86 deriving stock Functor
91−instance Bifunctor TheseTable where
89+instance Bifunctor (TheseTable context) where
92 bimap f g (TheseTable a b) = TheseTable (fmap f a) (fmap g b)
90 bimap f g (TheseTable a b) = TheseTable (fmap f a) (fmap g b)
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)
96 fs <.> as = TheseTable
96 fs <.> as = TheseTable
97 { here = here fs <> here as
97 { here = here fs <> here as
98 , there = there fs <.> there as
98 , there = there fs <.> there as
102−instance (Table Expr a, Semigroup a) => Applicative (TheseTable a)
102+instance (context ~ Expr, Table Expr a, Semigroup a) =>
103+ Applicative (TheseTable context a)
104 pure = thatTable
105 pure = thatTable
105 (<*>) = (<.>)
106 (<*>) = (<.>)
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)
109 TheseTable here1 ma >>- f = case ma >>- f' of
112 TheseTable here1 ma >>- f = case ma >>- f' of
110 mtb -> TheseTable
113 mtb -> TheseTable
111 { here = maybeTable here1 ((here1 <>) . fst) mtb
114 { here = maybeTable here1 ((here1 <>) . fst) mtb
@@ -116,12 +119,14 @@ instance (Table Expr a, Semigroup a) => Bind (TheseTable a) where
116 TheseTable here2 mb -> (here2,) <$> mb
119 TheseTable here2 mb -> (here2,) <$> mb
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)
120 (>>=) = (>>-)
125 (>>=) = (>>-)
123−instance (Table Expr a, Table Expr b, Semigroup a, Semigroup b) =>
128+instance (context ~ Expr, Table Expr a, Table Expr b, Semigroup a, Semigroup b) =>
124− Semigroup (TheseTable a b)
129+ Semigroup (TheseTable context a b)
126 a <> b = TheseTable
131 a <> b = TheseTable
127 { here = here a <> here b
132 { here = here a <> here b
@@ -131,67 +136,61 @@ instance (Table Expr a, Table Expr b, Semigroup a, Semigroup b) =>
133 ( Table context a, Table context b
138 ( Table context a, Table context b
134− , Nullifiable context
139+ , Nullifiable context, context ~ context'
136− => Table context (TheseTable a b)
141+ => Table context' (TheseTable context a b)
138− type Columns (TheseTable a b) = HTheseTable (Columns a) (Columns b)
143+ type Columns (TheseTable context a b) = HTheseTable (Columns a) (Columns b)
139− type Context (TheseTable a b) = Context a
144+ type Context (TheseTable context a b) = Context a
141 toColumns TheseTable {here, there} = HTheseTable
146 toColumns TheseTable {here, there} = HTheseTable
142− { hhereTag = hlabel $ HType $ encodeTag (toHereTag (tag here))
147+ { hhereTag = hlabel (HIdentity (tag here))
143 , hhere =
148 , hhere =
144 hlabel $ hnullify (nullifier (tag here) isNonNull) $ toColumns $
149 hlabel $ hnullify (nullifier (tag here) isNonNull) $ toColumns $
145 just here
150 just here
146− , hthereTag = hlabel $ HType $ encodeTag (toThereTag (tag there))
151+ , hthereTag = hlabel (HIdentity (tag there))
147 , hthere =
152 , hthere =
148 hlabel $ hnullify (nullifier (tag there) isNonNull) $ toColumns $
153 hlabel $ hnullify (nullifier (tag there) isNonNull) $ toColumns $
149 just there
154 just there
152 fromColumns HTheseTable {hhereTag, hhere, hthereTag, hthere} = TheseTable
157 fromColumns HTheseTable {hhereTag, hhere, hthereTag, hthere} = TheseTable
153− { here =
158+ { here = MaybeTable
155− tag = decodeTag $ unHIdentity $ hunlabel hhereTag
159+ { tag = unHIdentity $ hunlabel hhereTag
159− , just =
160+ , just =
160− fromColumns $
161+ fromColumns $
161− runIdentity $
162+ runIdentity $
162− hunnullify (\a -> pure . unnullifier a) $
163+ hunnullify (\a -> pure . unnullifier a) $
163− hunlabel
164+ hunlabel
166− , there =
167+ , there = MaybeTable
168− tag = decodeTag $ unHIdentity $ hunlabel hthereTag
168+ { tag = unHIdentity $ hunlabel hthereTag
172− , just =
169+ , just =
173− fromColumns $
170+ fromColumns $
174− runIdentity $
171+ runIdentity $
175− hunnullify (\a -> pure . unnullifier a) $
172+ hunnullify (\a -> pure . unnullifier a) $
176− hunlabel
173+ hunlabel
182 reify = liftA2 bimap reify reify
178 reify = liftA2 bimap reify reify
183 unreify = liftA2 bimap unreify unreify
179 unreify = liftA2 bimap unreify unreify
187− ( Nullifiable from, Nullifiable to
183+ ( Nullifiable from, from ~ from'
184+ , Nullifiable to, to ~ to'
188 , Recontextualize from to a1 b1
185 , Recontextualize from to a1 b1
189 , Recontextualize from to a2 b2
186 , Recontextualize from to a2 b2
191− => Recontextualize from to (TheseTable a1 a2) (TheseTable b1 b2)
188+ => Recontextualize from to (TheseTable from' a1 a2) (TheseTable to' b1 b2)
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)
195 eqTable = HTheseTable
194 eqTable = HTheseTable
196 { hhereTag = hlabel (HType Dict)
195 { hhereTag = hlabel (HType Dict)
197 , hhere = hlabel (hnullify (\_ Dict -> Dict) (eqTable @a))
196 , hhere = hlabel (hnullify (\_ Dict -> Dict) (eqTable @a))
@@ -200,7 +199,9 @@ instance (EqTable a, EqTable b) => EqTable (TheseTable a b) where
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 ordTable = HTheseTable
205 ordTable = HTheseTable
205 { hhereTag = hlabel (HType Dict)
206 { hhereTag = hlabel (HType Dict)
206 , hhere = hlabel (hnullify (\_ Dict -> Dict) (ordTable @a))
207 , hhere = hlabel (hnullify (\_ Dict -> Dict) (ordTable @a))
@@ -209,10 +210,11 @@ instance (OrdTable a, OrdTable b) => OrdTable (TheseTable a b) where
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)
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) =>
216 ToExprs x (These a b)
218 ToExprs x (These a b)
218 fromResult =
220 fromResult =
@@ -223,81 +225,73 @@ instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ TheseTable exprs1 exprs2) =>
223 bimap (toResult @exprs1) (toResult @exprs2)
225 bimap (toResult @exprs1) (toResult @exprs2)
226−toHereTag :: Tag "isJust" a -> Tag "hasHere" a
227−toHereTag Tag {..} = Tag {..}
230−toThereTag :: Tag "isJust" a -> Tag "hasThere" a
231−toThereTag Tag {..} = Tag {..}
234-- | Test if a 'TheseTable' was constructed with 'thisTable'.
228-- | Test if a 'TheseTable' was constructed with 'thisTable'.
236-- Corresponds to 'Data.These.Combinators.isThis'.
230-- Corresponds to 'Data.These.Combinators.isThis'.
237−isThisTable :: TheseTable a b -> Expr Bool
231+isThisTable :: TheseTable Expr a b -> Expr Bool
238isThisTable a = hasHereTable a &&. not_ (hasThereTable a)
232isThisTable a = hasHereTable a &&. not_ (hasThereTable a)
241-- | Test if a 'TheseTable' was constructed with 'thatTable'.
235-- | Test if a 'TheseTable' was constructed with 'thatTable'.
243-- Corresponds to 'Data.These.Combinators.isThat'.
237-- Corresponds to 'Data.These.Combinators.isThat'.
244−isThatTable :: TheseTable a b -> Expr Bool
238+isThatTable :: TheseTable Expr a b -> Expr Bool
245isThatTable a = not_ (hasHereTable a) &&. hasThereTable a
239isThatTable a = not_ (hasHereTable a) &&. hasThereTable a
248-- | Test if a 'TheseTable' was constructed with 'thoseTable'.
242-- | Test if a 'TheseTable' was constructed with 'thoseTable'.
250-- Corresponds to 'Data.These.Combinators.isThese'.
244-- Corresponds to 'Data.These.Combinators.isThese'.
251−isThoseTable :: TheseTable a b -> Expr Bool
245+isThoseTable :: TheseTable Expr a b -> Expr Bool
252isThoseTable a = hasHereTable a &&. hasThereTable a
246isThoseTable a = hasHereTable a &&. hasThereTable a
255-- | Test if the @a@ side of @TheseTable a b@ is present.
249-- | Test if the @a@ side of @TheseTable a b@ is present.
257-- Corresponds to 'Data.These.Combinators.hasHere'.
251-- Corresponds to 'Data.These.Combinators.hasHere'.
258−hasHereTable :: TheseTable a b -> Expr Bool
252+hasHereTable :: TheseTable Expr a b -> Expr Bool
259hasHereTable TheseTable {here} = isJustTable here
253hasHereTable TheseTable {here} = isJustTable here
262-- | Test if the @b@ table of @TheseTable a b@ is present.
256-- | Test if the @b@ table of @TheseTable a b@ is present.
264-- Corresponds to 'Data.These.Combinators.hasThere'.
258-- Corresponds to 'Data.These.Combinators.hasThere'.
265−hasThereTable :: TheseTable a b -> Expr Bool
259+hasThereTable :: TheseTable Expr a b -> Expr Bool
266hasThereTable TheseTable {there} = isJustTable there
260hasThereTable TheseTable {there} = isJustTable there
269-- | Attempt to project out the @a@ table of a @TheseTable a b@.
263-- | Attempt to project out the @a@ table of a @TheseTable a b@.
271-- Corresponds to 'Data.These.Combinators.justHere'.
265-- Corresponds to 'Data.These.Combinators.justHere'.
272−justHereTable :: TheseTable a b -> MaybeTable a
266+justHereTable :: TheseTable context a b -> MaybeTable context a
273justHereTable = here
267justHereTable = here
276-- | Attempt to project out the @b@ table of a @TheseTable a b@.
270-- | Attempt to project out the @b@ table of a @TheseTable a b@.
278-- Corresponds to 'Data.These.Combinators.justThere'.
272-- Corresponds to 'Data.These.Combinators.justThere'.
279−justThereTable :: TheseTable a b -> MaybeTable b
273+justThereTable :: TheseTable context a b -> MaybeTable context b
280justThereTable = there
274justThereTable = there
283-- | Construct a @TheseTable@. Corresponds to 'This'.
277-- | 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
285thisTable a = TheseTable (justTable a) nothingTable
279thisTable a = TheseTable (justTable a) nothingTable
288-- | Construct a @TheseTable@. Corresponds to 'That'.
282-- | 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
290thatTable b = TheseTable nothingTable (justTable b)
284thatTable b = TheseTable nothingTable (justTable b)
293-- | Construct a @TheseTable@. Corresponds to 'These'.
287-- | Construct a @TheseTable@. Corresponds to 'These'.
294−thoseTable :: a -> b -> TheseTable a b
288+thoseTable :: a -> b -> TheseTable Expr a b
295thoseTable a b = TheseTable (justTable a) (justTable b)
289thoseTable a b = TheseTable (justTable a) (justTable b)
298-- | Pattern match on a 'TheseTable'. Corresponds to 'these'.
292-- | Pattern match on a 'TheseTable'. Corresponds to 'these'.
299theseTable :: Table Expr c
293theseTable :: 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
301theseTable f g h TheseTable {here, there} =
295theseTable f g h TheseTable {here, there} =
302 maybeTable
296 maybeTable
303 (maybeTable undefined f here)
297 (maybeTable undefined f here)
@@ -305,6 +299,19 @@ theseTable f g h TheseTable {here, there} =
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
308-- | Construct a 'TheseTable' in the 'Name' context. This can be useful if you
315-- | Construct a 'TheseTable' in the 'Name' context. This can be useful if you
309-- have a 'TheseTable' that you are storing in a table and need to construct a
316-- have a 'TheseTable' that you are storing in a table and need to construct a
310-- 'TableSchema'.
317-- 'TableSchema'.
@@ -317,7 +324,7 @@ nameTheseTable :: ()
317 -- ^ Names of the columns in the @a@ table.
324 -- ^ Names of the columns in the @a@ table.
319 -- ^ Names of the columns in the @b@ table.
326 -- ^ Names of the columns in the @b@ table.
320− -> TheseTable a b
327+ -> TheseTable Name a b
321nameTheseTable here there a b =
328nameTheseTable here there a b =
322 TheseTable
329 TheseTable
323 { here = nameMaybeTable here a
330 { here = nameMaybeTable here a