@@ -21,6 +21,7 @@ module Rel8.Table.ADT
2121 , InsertADT, insertADT
2222 , NameADT, nameADT
2323 , AggregateADT, aggregateADT
24+ , AggregateADT', aggregateADT'
2425 )
2526where
2627
@@ -32,19 +33,19 @@ import Data.Type.Equality ( (:~:)( Refl ) )
3233import Prelude
3334
3435-- rel8
35−import Rel8.Aggregate ( Col( Aggregation ), Aggregate, mapInputs )
36+import Rel8.Aggregate ( Col( Aggregation ), Aggregate )
3637import Rel8.Expr ( Col( DB ), Expr )
3738import Rel8.Expr.Aggregate ( groupByExpr )
3839import Rel8.Expr.Eq ( (==.) )
3940import Rel8.Expr.Null ( nullify, snull, unsafeUnnullify )
40−import Rel8.Expr.Opaleye ( fromPrimExpr, toPrimExpr )
4141import Rel8.Expr.Serialize ( litExpr )
42+import Rel8.FCF ( Compose )
4243import Rel8.Generic.Construction.ADT
4344 ( GConstructableADT
4445 , GBuildADT, gbuildADT, gunbuildADT
4546 , GConstructADT, gconstructADT, gdeconstructADT
4647 , CorepConstructors, GConstructors, gcindex, gctabulate
47− , CorepFields, GFields, gfindex, gftabulate
48+ , CorepFields, gfindex, gftabulate, gftraverse
4849 )
4950import Rel8.Generic.Rel8able
5051 ( Rel8able, Algebra
@@ -55,7 +56,6 @@ import Rel8.Generic.Rel8able
5556import qualified Rel8.Generic.Table.ADT as G
5657import qualified Rel8.Kind.Algebra as K
5758import Rel8.Kind.Necessity ( SNecessity( SOptional, SRequired ) )
58−import Rel8.Schema.Context ( Col )
5959import Rel8.Schema.Context.Nullify ( runTag )
6060import Rel8.Schema.HTable ( HTable )
6161import Rel8.Schema.HTable.Type ( HType( HType ) )
@@ -73,6 +73,9 @@ import Rel8.Table
7373import Rel8.Table.Bool ( case_ )
7474import Rel8.Type.Tag ( Tag )
7575
76+-- semigroupoids
77+import Data.Functor.Apply ( Apply, MaybeApply( MaybeApply ), liftF2 )
78+
7679
7780type ADT :: K.Rel8able -> K.Rel8able
7881newtype ADT t context = ADT (GColumnsADT t (Col context))
@@ -100,6 +103,7 @@ type ConstructableADT :: K.Rel8able -> Constraint
100103class
101104 ( CorepConstructors TUnreify (GRep t (Reify Expr))
102105 , CorepConstructors TUnreify (GRep t (Reify Insert))
106+ , CorepFields (Compose Aggregate TUnreify) (GRep t (Reify Expr))
103107 , CorepFields TUnreify (GRep t (Reify Aggregate))
104108 , CorepFields TUnreify (GRep t (Reify Expr))
105109 , CorepFields TUnreify (GRep t (Reify Name))
@@ -119,6 +123,7 @@ class
119123instance
120124 ( CorepConstructors TUnreify (GRep t (Reify Expr))
121125 , CorepConstructors TUnreify (GRep t (Reify Insert))
126+ , CorepFields (Compose Aggregate TUnreify) (GRep t (Reify Expr))
122127 , CorepFields TUnreify (GRep t (Reify Aggregate))
123128 , CorepFields TUnreify (GRep t (Reify Expr))
124129 , CorepFields TUnreify (GRep t (Reify Name))
@@ -235,12 +240,63 @@ nameADT tag = gftabulate @TUnreify @(GRep t (Reify Name)) @(ADT t Name) $
235240type AggregateADT :: K.Rel8able -> Type
236241type AggregateADT t = forall r.
237242 GBuildADT TUnreify (GRep t (Reify Expr))
238− (GBuildADT TUnreify (GRep t (Reify Aggregate)) r -> r)
243+ (GBuildADT (Compose Aggregate TUnreify) (GRep t (Reify Expr)) r -> r)
239244
240245
241246aggregateADT :: forall t. ConstructableADT t
242− => AggregateADT t -> ADT t Expr -> ADT t Aggregate
247+ => AggregateADT t -> ADT t Expr -> Aggregate (ADT t Expr)
243248aggregateADT builder (ADT columns) = f exprs $
249+ liftF1½
250+ (\tag' ->
251+ ADT .
252+ hunreify .
253+ gbuildADT
254+ @(TTable (Reify Expr))
255+ @TColumns
256+ @TUnreify
257+ @(Col (Reify Expr))
258+ @(GRep t (Reify Expr))
259+ (\(_ :: proxy x) -> toColumns . reify @_ @x Refl)
260+ (\tag'' SSpec {nullity} (Reify (DB a)) ->
261+ Reify $ DB $ runTag nullity (tag ==. litExpr tag'') a)
262+ (HType (Reify (DB tag'))))
263+ (groupByExpr tag) .
264+ gftraverse @TUnreify @(GRep t (Reify Expr)) @_ @Aggregate (MaybeApply . Left)
265+ where
266+ f e =
267+ gfindex
268+ @TUnreify
269+ @(GRep t (Reify Expr))
270+ @(GBuildADT (Compose Aggregate TUnreify) (GRep t (Reify Expr)) (Aggregate (ADT t Expr)) -> Aggregate (ADT t Expr))
271+ (builder @(Aggregate (ADT t Expr)))
272+ e .
273+ gftabulate
274+ @(Compose Aggregate TUnreify)
275+ @(GRep t (Reify Expr))
276+ @(Aggregate (ADT t Expr))
277+ (HType (Reify (DB tag)), exprs) =
278+ gunbuildADT
279+ @(TTable (Reify Expr))
280+ @TColumns
281+ @TUnreify
282+ @(Col (Reify Expr))
283+ @(GRep t (Reify Expr))
284+ (\(_ :: proxy x) -> unreify @_ @x Refl . fromColumns)
285+ (\SSpec {nullity} -> case nullity of
286+ Null -> id
287+ NotNull -> \(Reify (DB a)) -> Reify (DB (unsafeUnnullify a)))
288+ (hreify columns)
289+
290+
291+type AggregateADT' :: K.Rel8able -> Type
292+type AggregateADT' t = forall r.
293+ GBuildADT TUnreify (GRep t (Reify Expr))
294+ (GBuildADT TUnreify (GRep t (Reify Aggregate)) r -> r)
295+
296+
297+aggregateADT' :: forall t. ConstructableADT t
298+ => AggregateADT' t -> ADT t Expr -> ADT t Aggregate
299+aggregateADT' builder (ADT columns) = f exprs $
244300 ADT .
245301 hunreify .
246302 gbuildADT
@@ -250,14 +306,8 @@ aggregateADT builder (ADT columns) = f exprs $
250306 @(Col (Reify Aggregate))
251307 @(GRep t (Reify Aggregate))
252308 (\(_ :: proxy x) -> toColumns . reify @_ @x Refl)
253− (\tag' SSpec {nullity} (Reify (Aggregation aggregate)) ->
254− let
255− condition = tag ==. litExpr tag'
256− in
257− Reify $
258− Aggregation $
259− mapInputs (toPrimExpr . runTag nullity condition . fromPrimExpr) $
260− runTag nullity condition <$> aggregate)
309+ (\tag' SSpec {nullity} (Reify (Aggregation a)) ->
310+ Reify $ Aggregation $ runTag nullity (tag ==. litExpr tag') <$> a)
261311 (HType (Reify (Aggregation (groupByExpr tag))))
262312 where
263313 f e =
@@ -283,3 +333,9 @@ aggregateADT builder (ADT columns) = f exprs $
283333 Null -> id
284334 NotNull -> \(Reify (DB a)) -> Reify (DB (unsafeUnnullify a)))
285335 (hreify columns)
336+
337+
338+liftF1½ :: Apply v => (a -> b -> c) -> v a -> MaybeApply v b -> v c
339+liftF1½ f a (MaybeApply eb) = case eb of
340+ Left b -> liftF2 f a b
341+ Right b -> fmap (`f` b) a