@@ -9,14 +9,14 @@
9{-# language UndecidableInstances #-}
9{-# language UndecidableInstances #-}
11module Rel8.Aggregate
11module Rel8.Aggregate
12− ( Aggregate(..), foldInputs, mapInputs
12+ ( Aggregate(..), zipOutputs
13 , Aggregator(..), unsafeMakeAggregate
13 , Aggregator(..), unsafeMakeAggregate
14 , Aggregates
14 , Aggregates
19−import Data.Functor.Const ( Const( Const ), getConst )
19+import Control.Applicative ( liftA2 )
20import Data.Functor.Identity ( Identity( Identity ) )
20import Data.Functor.Identity ( Identity( Identity ) )
21import Data.Kind ( Constraint, Type )
21import Data.Kind ( Constraint, Type )
22import Prelude
22import Prelude
@@ -40,11 +40,7 @@ import Rel8.Table.Transpose ( Transposes )
40import Rel8.Type ( DBType )
40import Rel8.Type ( DBType )
43−-- | An @Aggregate a@ describes how to aggregate @Table@s of type @a@. You can
43+-- | 'Aggregate' is a special context used by 'Rel8.aggregate'.
44−-- unpack an @Aggregate@ back to @a@ by running it with 'Rel8.aggregate'. As
45−-- @Aggregate@ is almost an 'Applicative' functor - but there is no 'pure'
46−-- operation. This means 'Aggregate' is an instance of 'Apply', and you can
47−-- combine @Aggregate@s using the @<.>@ combinator.
48type Aggregate :: K.Context
44type Aggregate :: K.Context
49newtype Aggregate a = Aggregate (Opaleye.Aggregator () (Expr a))
45newtype Aggregate a = Aggregate (Opaleye.Aggregator () (Expr a))
@@ -61,28 +57,16 @@ instance Sql DBType a => Table Aggregate (Aggregate a) where
61 fromResult (HIdentity (Identity a)) = a
57 fromResult (HIdentity (Identity a)) = a
64−-- | @Aggregates a b@ means that the columns in @a@ are all 'Aggregate' 'Expr's
60+-- | @Aggregates a b@ means that the columns in @a@ are all 'Aggregate's
65−-- for the columns in @b@.
61+-- for the 'Expr' columns in @b@.
66type Aggregates :: Type -> Type -> Constraint
62type Aggregates :: Type -> Type -> Constraint
67class Transposes Aggregate Expr aggregates exprs => Aggregates aggregates exprs
63class Transposes Aggregate Expr aggregates exprs => Aggregates aggregates exprs
68instance Transposes Aggregate Expr aggregates exprs => Aggregates aggregates exprs
64instance Transposes Aggregate Expr aggregates exprs => Aggregates aggregates exprs
71−foldInputs :: forall (a :: Type) (b :: Type). Monoid b
67+zipOutputs :: ()
72− => (Maybe Aggregator -> Opaleye.PrimExpr -> b) -> Aggregate a -> b
68+ => (Expr a -> Expr b -> Expr c) -> Aggregate a -> Aggregate b -> Aggregate c
73−foldInputs f (Aggregate (Opaleye.Aggregator (Opaleye.PackMap agg))) =
69+zipOutputs f (Aggregate a) (Aggregate b) = Aggregate (liftA2 f a b)
74− getConst $ flip agg () $ \(aggregator, a) ->
75− Const $ f (detuplize <$> aggregator) a
77− detuplize (operation, ordering, distinction) =
78− Aggregator {operation, ordering, distinction}
81−mapInputs :: forall (a :: Type). ()
82− => (Opaleye.PrimExpr -> Opaleye.PrimExpr) -> Aggregate a -> Aggregate a
83−mapInputs transform (Aggregate (Opaleye.Aggregator (Opaleye.PackMap agg))) =
84− Aggregate $ Opaleye.Aggregator $ Opaleye.PackMap $ agg . \f input ->
85− f (fmap transform input)
88type Aggregator :: Type
72type Aggregator :: Type