javelin 0.1.2.0 → 0.1.3.0
raw patch · 6 files changed
+71/−11 lines, 6 filesdep ~basedep ~deepseqPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, deepseq
API changes (from Hackage documentation)
Files
- CHANGELOG.md +6/−0
- javelin.cabal +7/−7
- src/Data/Series.hs +15/−0
- src/Data/Series/Generic/Aggregation.hs +9/−3
- src/Data/Series/Unboxed.hs +13/−0
- test/Test/Data/Series/Generic/Aggregation.hs +21/−1
CHANGELOG.md view
@@ -1,5 +1,11 @@ # Revision history for javelin +## Release 0.1.3.0++* Improved performance for the `aggregateWith` function.+* Ensured that arguments are consumed in the expected order using `foldWith`.+* Documentation improvements.+ ## Release 0.1.2.0 * Fixed an issue where `Series` could be corrupted while using `aggregateWith`.
javelin.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: javelin-version: 0.1.2.0+version: 0.1.3.0 synopsis: Labeled one-dimensional arrays license: MIT license-file: LICENSE@@ -10,9 +10,9 @@ build-type: Simple extra-doc-files: CHANGELOG.md files/aapl.txt-tested-with: GHC ==9.8.1 - || ==9.6.3- || ==9.4.7 +tested-with: GHC ==9.8.2 + || ==9.6.4+ || ==9.4.8 description: This package implements 'Series', labeled one-dimensional arrays@@ -99,7 +99,7 @@ ghc-options: -rtsopts hs-source-dirs: benchmarks main-is: Comparison.hs- build-depends: base,+ build-depends: base >=4.15.0.0 && <4.20, containers, foldl, mono-traversable,@@ -120,7 +120,7 @@ ghc-options: -rtsopts hs-source-dirs: benchmarks main-is: Operations.hs- build-depends: base,+ build-depends: base>=4.15.0.0 && <4.20, containers, deepseq, foldl,@@ -132,5 +132,5 @@ import: common main-is: bench-report.hs hs-source-dirs: scripts- build-depends: base, + build-depends: base>=4.15.0.0 && <4.20, csv ^>=0.1
src/Data/Series.hs view
@@ -1081,6 +1081,21 @@ -- | Aggregate each group in a 'Grouping' using a binary function. -- While this is not as expressive as 'aggregateWith', users looking for maximum -- performance should use 'foldWith' as much as possible.+--+-- >>> type Date = (Int, String)+-- >>> month :: (Date -> String) = snd+-- >>> :{ +-- let xs = Series.fromList [ ((2020, "January") :: Date, 0 :: Int)+-- , ((2021, "January"), -5)+-- , ((2020, "June") , 20)+-- , ((2021, "June") , 25) +-- ]+-- in xs `groupBy` month `foldWith` min+-- :}+-- index | values+-- ----- | ------+-- "January" | -5+-- "June" | 20 foldWith :: Ord g => Grouping k g a -> (a -> a -> a)
src/Data/Series/Generic/Aggregation.hs view
@@ -95,10 +95,14 @@ -- We're using a list fold to limit the number of -- type constraints. This is about as fast as it is -- with a Vector fold- $ Data.List.foldl' acc mempty + $ Data.List.foldl' acc Map.empty + -- See the performance note for `Data.Map.Strict.insertWith`+ -- (https://hackage.haskell.org/package/containers-0.7/docs/Data-Map-Strict.html#v:insertWith)+ -- which explains that reversing the list leads to better performance+ $ reverse $ GSeries.toList xs where- acc !m (key, val) = Map.insertWith (flip (<>)) -- Flipping arguments to ensure that keys are ordered as expected+ acc !m (key, val) = Map.insertWith (++) (by key) (Data.List.singleton (key, val)) m@@ -132,7 +136,9 @@ -- We're using a list fold to limit the number of -- type constraints. This is about as fast as it is -- with a Vector fold- $ Data.List.foldl' acc mempty + $ Data.List.foldl' acc mempty+ -- We want to make sure that the order of folded arguments is intuitive+ $ reverse $ GSeries.toList xs where acc !m (key, val) = Map.insertWith f (by key) val m
src/Data/Series/Unboxed.hs view
@@ -1003,6 +1003,19 @@ -- | Aggregate each group in a 'Grouping' using a binary function. -- While this is not as expressive as 'aggregateWith', users looking for maximum -- performance should use 'foldWith' as much as possible.+--+-- >>> :{ +-- let xs = Series.fromList [ ((1, 1) :: (Int, Int), 0 :: Int)+-- , ((2, 1), -5)+-- , ((3, 2), 20)+-- , ((4, 2), 25) +-- ]+-- in xs `groupBy` snd `foldWith` min+-- :}+-- index | values+-- ----- | ------+-- 1 | -5+-- 2 | 20 foldWith :: (Ord g, Unbox a) => Grouping k g a -> (a -> a -> a)
test/Test/Data/Series/Generic/Aggregation.hs view
@@ -29,7 +29,13 @@ testGroupBy :: TestTree-testGroupBy = testGroup "Data.Series.Generic.groupBy" [ testGroupBy1, testGroupBy2, testGroupBy3, testGroupBy4 ]+testGroupBy = testGroup "Data.Series.Generic.groupBy" + [ testGroupBy1+ , testGroupBy2+ , testGroupBy3+ , testGroupBy4+ , testGroupBy5 + ] where testGroupBy1 = testCase "groupBy" $ do let (series :: Series Vector String Int) = fromStrictMap $ MS.fromList [("aa", 1), ("ab", 2), ("c", 3), ("dc", 4), ("ae", 5)]@@ -52,6 +58,9 @@ assertEqual mempty expectation $ series `groupBy` fst `aggregateWith` (IS.fromList . Series.toList . flip Series.mapIndex snd) + -- The following example resulted in an exception+ -- when the implementation of `aggregateWith` didn't aggregate keys in the+ -- right order testGroupBy4 = testCase "groupBy" $ do let (series :: Series Vector (Int, Int) Int) = fromStrictMap $ MS.fromList $ zip (zip [0,1,2,3,4,5] [1,1,2,2,3,3]) [2,1,2,1,2,1] expectation = fromStrictMap $ MS.fromList [ (1, Vector.fromList [2,1])@@ -60,6 +69,17 @@ ] assertEqual mempty expectation $ series `groupBy` snd `aggregateWith` (Series.values)+ + -- The following test ensures that the order of folding in `foldWith` is intuitive.+ testGroupBy5 = testCase "groupBy" $ do+ let (series :: Series Vector Int [Int]) = fromStrictMap $ MS.fromList $ zip [0,1,2,3,4,5] [[0],[1],[2],[3],[4],[5]]+ expectation = fromStrictMap $ MS.fromList [ (True, [0, 2, 4])+ , (False, [1, 3, 5])+ ]+ + assertEqual mempty expectation $ series `groupBy` isEven `foldWith` (++)+ where+ isEven i = i `mod` 2 == 0 testWindowing :: TestTree