@@ -9,14 +9,14 @@
99{-# language UndecidableInstances #-}
1010
1111module Rel8.Aggregate
12− ( Aggregate(..), foldInputs, mapInputs
12+ ( Aggregate(..), zipOutputs
1313 , Aggregator(..), unsafeMakeAggregate
1414 , Aggregates
1515 )
1616where
1717
1818-- base
19−import Data.Functor.Const ( Const( Const ), getConst )
19+import Control.Applicative ( liftA2 )
2020import Data.Functor.Identity ( Identity( Identity ) )
2121import Data.Kind ( Constraint, Type )
2222import Prelude
@@ -40,11 +40,7 @@ import Rel8.Table.Transpose ( Transposes )
4040import Rel8.Type ( DBType )
4141
4242
43−-- | An @Aggregate a@ describes how to aggregate @Table@s of type @a@. You can
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.
43+-- | 'Aggregate' is a special context used by 'Rel8.aggregate'.
4844type Aggregate :: K.Context
4945newtype Aggregate a = Aggregate (Opaleye.Aggregator () (Expr a))
5046
@@ -61,28 +57,16 @@ instance Sql DBType a => Table Aggregate (Aggregate a) where
6157 fromResult (HIdentity (Identity a)) = a
6258
6359
64−-- | @Aggregates a b@ means that the columns in @a@ are all 'Aggregate' 'Expr's
65−-- for the columns in @b@.
60+-- | @Aggregates a b@ means that the columns in @a@ are all 'Aggregate's
61+-- for the 'Expr' columns in @b@.
6662type Aggregates :: Type -> Type -> Constraint
6763class Transposes Aggregate Expr aggregates exprs => Aggregates aggregates exprs
6864instance Transposes Aggregate Expr aggregates exprs => Aggregates aggregates exprs
6965
7066
71−foldInputs :: forall (a :: Type) (b :: Type). Monoid b
72− => (Maybe Aggregator -> Opaleye.PrimExpr -> b) -> Aggregate a -> b
73−foldInputs f (Aggregate (Opaleye.Aggregator (Opaleye.PackMap agg))) =
74− getConst $ flip agg () $ \(aggregator, a) ->
75− Const $ f (detuplize <$> aggregator) a
76− where
77− detuplize (operation, ordering, distinction) =
78− Aggregator {operation, ordering, distinction}
79−
80−
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)
67+zipOutputs :: ()
68+ => (Expr a -> Expr b -> Expr c) -> Aggregate a -> Aggregate b -> Aggregate c
69+zipOutputs f (Aggregate a) (Aggregate b) = Aggregate (liftA2 f a b)
8670
8771
8872type Aggregator :: Type