@@ -26,7 +26,7 @@ module Rel8.Tabulate
26 , difference
26 , difference
27 , aggregateTabulation
27 , aggregateTabulation
28 , orderTabulation
28 , orderTabulation
29− , singularize
29+ , distinctTabulation
30 , optionalTabulation
30 , optionalTabulation
31 , manyTabulation
31 , manyTabulation
32 , someTabulation
32 , someTabulation
@@ -48,13 +48,14 @@ import Rel8.Expr ( Expr )
48import Rel8.Order ( Order )
48import Rel8.Order ( Order )
49import Rel8.Query ( Query )
49import Rel8.Query ( Query )
50import Rel8.Query.Aggregate ( aggregate )
50import Rel8.Query.Aggregate ( aggregate )
51+import Rel8.Query.Distinct ( distinctOn )
51import Rel8.Query.Exists ( withBy, withoutBy )
52import Rel8.Query.Exists ( withBy, withoutBy )
52import Rel8.Query.Filter ( filter, where_ )
53import Rel8.Query.Filter ( filter, where_ )
53import Rel8.Query.Maybe ( optional )
54import Rel8.Query.Maybe ( optional )
54import Rel8.Query.Order ( orderBy )
55import Rel8.Query.Order ( orderBy )
55import Rel8.Query.These ( alignBy )
56import Rel8.Query.These ( alignBy )
56import Rel8.Table ( Table )
57import Rel8.Table ( Table )
57−import Rel8.Table.Aggregate ( groupBy, headAgg, listAgg, nonEmptyAgg )
58+import Rel8.Table.Aggregate ( groupBy, listAgg, nonEmptyAgg )
58import Rel8.Table.Alternative
59import Rel8.Table.Alternative
59 ( AltTable, (<|>:)
60 ( AltTable, (<|>:)
60 , AlternativeTable, emptyTable
61 , AlternativeTable, emptyTable
@@ -63,6 +64,8 @@ import Rel8.Table.Eq ( EqTable, (==:) )
63import Rel8.Table.List ( ListTable )
64import Rel8.Table.List ( ListTable )
64import Rel8.Table.Maybe ( MaybeTable, maybeTable )
65import Rel8.Table.Maybe ( MaybeTable, maybeTable )
65import Rel8.Table.NonEmpty ( NonEmptyTable )
66import Rel8.Table.NonEmpty ( NonEmptyTable )
67+import Rel8.Table.Ord ( OrdTable )
68+import Rel8.Table.Order ( ascTable )
66import Rel8.Table.These ( TheseTable, theseTable )
69import Rel8.Table.These ( TheseTable, theseTable )
68-- semigroupoids
71-- semigroupoids
@@ -337,26 +340,26 @@ difference kas kbs = do
338aggregateTabulation :: EqTable k
341aggregateTabulation :: EqTable k
339 => Tabulation k (Aggregate a) -> Tabulation k a
342 => Tabulation k (Aggregate a) -> Tabulation k a
340−aggregateTabulation kas = do
342− fromQuery $ aggregate $ bitraverse1 groupBy id <$> as
343+aggregateTabulation = mapQuery (aggregate . fmap (bitraverse1 groupBy id))
345−-- | 'orderTabulation' orders the /values/ of a 'Tabulation' (not the keys).
346+-- | 'orderTabulation' orders the /values/ of a 'Tabulation' within each key.
346-- In general this is meaningless, but if used together with 'manyTabulation'
348-- In general this is meaningless, but if used together with 'manyTabulation'
347-- or 'someTabulation', the resulting lists will be ordered according to
349-- or 'someTabulation', the resulting lists will be ordered according to
348-- ordering given to 'orderTabulation'.
350-- ordering given to 'orderTabulation'.
349−orderTabulation :: Order a -> Tabulation k a -> Tabulation k a
351+orderTabulation :: OrdTable k => Order a -> Tabulation k a -> Tabulation k a
350−orderTabulation ordering (Tabulation as) =
352+orderTabulation ordering = mapQuery $ orderBy ordering'
351− Tabulation $ orderBy (snd >$< ordering) . as
353+ where
354+ ordering' = (fst >$< ascTable) <> (snd >$< ordering)
354-- | Turns the given 'Tabulation' from a \"multimap\" into a \"map\". If there
357-- | Turns the given 'Tabulation' from a \"multimap\" into a \"map\". If there
355-- is more than one value at a particular key, only the first one is kept.
358-- is more than one value at a particular key, only the first one is kept.
356-- \"First\" is in general undefined, but 'orderTabulation' can be used to
359-- \"First\" is in general undefined, but 'orderTabulation' can be used to
357-- make it deterministic.
360-- make it deterministic.
358−singularize :: (EqTable k, Table Expr a) => Tabulation k a -> Tabulation k a
361+distinctTabulation :: EqTable k => Tabulation k a -> Tabulation k a
359−singularize = aggregateTabulation . fmap headAgg
362+distinctTabulation = mapQuery (distinctOn fst)
362optionalTabulation :: EqTable k
365optionalTabulation :: EqTable k
@@ -380,6 +383,11 @@ someTabulation :: (EqTable k, Table Expr a)
380someTabulation = aggregateTabulation . fmap nonEmptyAgg
383someTabulation = aggregateTabulation . fmap nonEmptyAgg
386+mapQuery :: (Query (k, a) -> Query (k, b)) -> Tabulation k a -> Tabulation k b
387+mapQuery f (Tabulation query) = Tabulation $ \k ->
388+ first Just <$> f (first (fromMaybe k) <$> query k)
383toQuery :: Tabulation k a -> Tabulation k (Query (k, a))
391toQuery :: Tabulation k a -> Tabulation k (Query (k, a))
384toQuery (Tabulation as) = Tabulation $ \k ->
392toQuery (Tabulation as) = Tabulation $ \k ->
385 pure (Nothing, first (fromMaybe k) <$> as k)
393 pure (Nothing, first (fromMaybe k) <$> as k)