From 4b7bf60e85d82a5d86199f173989c2bf360026af Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 15 Jun 2026 05:23:00 +0530 Subject: [PATCH 1/7] Update nix flake --- flake.lock | 10 +++++----- flake.nix | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 05f06b6..114d59a 100644 --- a/flake.lock +++ b/flake.lock @@ -7,16 +7,16 @@ "nixpkgs-darwin": "nixpkgs-darwin" }, "locked": { - "lastModified": 1776376313, - "narHash": "sha256-lfL+xfAZVM4nYLEggaRo3nBNxTHKgjdxJTcEHkM8P7Q=", + "lastModified": 1776414440, + "narHash": "sha256-Be67u+Qea2sEuI+3BVjkc+o4fYgRT/fOANGNAp2OuFk=", "ref": "refs/heads/master", - "rev": "187bde6bd362eced707ed96198ddc193af66ff42", - "revCount": 123, + "rev": "69728978adc44f53b3dd907acb2eb5bd2415fd60", + "revCount": 125, "type": "git", "url": "ssh://git@github.com/composewell/streamly-packages" }, "original": { - "rev": "187bde6bd362eced707ed96198ddc193af66ff42", + "rev": "69728978adc44f53b3dd907acb2eb5bd2415fd60", "type": "git", "url": "ssh://git@github.com/composewell/streamly-packages" } diff --git a/flake.nix b/flake.nix index 6a50244..5629dc5 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "streamly-statistics"; inputs = { - basepkgs.url = "git+ssh://git@github.com/composewell/streamly-packages?rev=187bde6bd362eced707ed96198ddc193af66ff42"; + basepkgs.url = "git+ssh://git@github.com/composewell/streamly-packages?rev=69728978adc44f53b3dd907acb2eb5bd2415fd60"; nixpkgs.follows = "basepkgs/nixpkgs"; nixpkgs-darwin.follows = "basepkgs/nixpkgs-darwin"; }; From 632e04cc7fc5524f36fdbf3187905d9ece5efd74 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 15 Jun 2026 05:23:26 +0530 Subject: [PATCH 2/7] Allow streamly development version --- streamly-statistics.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/streamly-statistics.cabal b/streamly-statistics.cabal index 09c7042..f9e70ce 100644 --- a/streamly-statistics.cabal +++ b/streamly-statistics.cabal @@ -113,7 +113,7 @@ library Streamly.Statistics , Streamly.Statistics.Scanl build-depends: base >= 4.9 && < 5 - , streamly-core >= 0.3.0 && < 0.4.0 + , streamly-core >= 0.3.0 && < 0.5 , containers >= 0.5 && < 0.9 , random >= 1.2 && < 1.4 , mwc-random >= 0.15 && < 0.16 From b2a2b308183444ebcfd165e8deb2981b53ca9f91 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 15 Jun 2026 06:18:33 +0530 Subject: [PATCH 3/7] Deprecate incremental folds in favor of Scans --- src/Streamly/Statistics.hs | 142 +++++++++++++------------------ src/Streamly/Statistics/Scanl.hs | 22 ++--- 2 files changed, 69 insertions(+), 95 deletions(-) diff --git a/src/Streamly/Statistics.hs b/src/Streamly/Statistics.hs index cda3630..e16eabd 100644 --- a/src/Streamly/Statistics.hs +++ b/src/Streamly/Statistics.hs @@ -71,110 +71,67 @@ {-# LANGUAGE ScopedTypeVariables #-} module Streamly.Statistics ( - -- * Incremental Folds - -- | Folds of type @Fold m (a, Maybe a) b@ are incremental sliding window - -- folds. An input of type @(a, Nothing)@ indicates that the input element - -- @a@ is being inserted in the window without ejecting an old value - -- increasing the window size by 1. An input of type @(a, Just a)@ - -- indicates that the first element is being inserted in the window and the - -- second element is being removed from the window, the window size remains - -- the same. The window size can only increase and never decrease. - -- - -- You can compute the statistics over the entire stream using sliding - -- window folds by keeping the second element of the input tuple as - -- @Nothing@. - -- - lmap - , Window.cumulative + -- ** Weighted Means + -- | Exponential Smoothing. + ewmaAfterMean + + -- ** Resampling + , resample + , foldResamples + , jackKnifeMean + , jackKnifeVariance + , jackKnifeStdDev - -- * Summary Statistics - -- | See https://en.wikipedia.org/wiki/Summary_statistics . + -- ** Probability Distribution + , frequency' + , mode - -- ** Sums + -- Histograms + , HistBin (..) + , binOffsetSize + , binFromSizeN + , binFromToN + , binBoundaries + , histogram + + -- * Transforms + , fft + + -- * Deprecated + -- | Incremental Folds in this module have been deprecated in favor of the + -- incremental scans in the Scanl module. + + , ewma + , ewmaRampUpSmoothing + , lmap + , Window.cumulative , length , sum , sumInt , powerSum - - -- ** Location - -- | See https://en.wikipedia.org/wiki/Location_parameter . - -- - -- See https://en.wikipedia.org/wiki/Central_tendency . , minimum , maximum , rawMoment , rawMomentFrac - - -- Pythagorean means (https://en.wikipedia.org/wiki/Pythagorean_means) , mean , welfordMean , geometricMean , harmonicMean - , quadraticMean - - -- Generalized mean , powerMean , powerMeanFrac - - -- ** Weighted Means - -- | Exponential Smoothing. - , ewma - , ewmaAfterMean - , ewmaRampUpSmoothing - - -- ** Spread - -- | Second order central moment is a statistical measure of dispersion. - -- The \(k\)th moment about the mean (or \(k\)th central moment) is defined - -- as: - -- - -- \(\mu_k = \frac{1}{n}\sum_{i=1}^n {(x_{i}-\mu)}^k\) - -- - -- See https://mathworld.wolfram.com/CentralMoment.html . - -- - -- See https://en.wikipedia.org/wiki/Statistical_dispersion . , range , md , variance , stdDev - - -- ** Shape - -- | Third and fourth order central moments are a measure of shape. - -- - -- See https://en.wikipedia.org/wiki/Shape_parameter . - -- - -- See https://en.wikipedia.org/wiki/Standardized_moment . , skewness , kurtosis - - -- XXX Move to Statistics.Sample or Statistics.Estimation module? - -- ** Estimation , sampleVariance , sampleStdDev , stdErrMean - - -- ** Resampling - , resample - , foldResamples - , jackKnifeMean - , jackKnifeVariance - , jackKnifeStdDev - - -- ** Probability Distribution , frequency - , frequency' - , mode - -- Histograms - , HistBin (..) - , binOffsetSize - , binFromSizeN - , binFromToN - , binBoundaries - , histogram - -- * Transforms - , fft ) where @@ -222,25 +179,23 @@ import Prelude hiding (length, sum, minimum, maximum) -- Re-exports ------------------------------------------------------------------------------- --- XXX Deprecate these once the streamly functions are released. - --- {-# DEPRECATED lmap "Use Streamly.Data.Fold.windowLmap instead" #-} +{-# DEPRECATED lmap "Use Streamly.Internal.Data.Scanl.incrRollingMap instead" #-} lmap :: (c -> a) -> Fold m (a, Maybe a) b -> Fold m (c, Maybe c) b lmap = Window.windowLmap --- {-# DEPRECATED length "Use Streamly.Data.Fold.windowLength instead" #-} +{-# DEPRECATED length "Use Streamly.Internal.Data.Scanl.incrCount instead" #-} length :: (Monad m, Num b) => Fold m (a, Maybe a) b length = Window.windowLength --- {-# DEPRECATED sum "Use Streamly.Data.Fold.windowSum instead" #-} +{-# DEPRECATED sum "Use Streamly.Internal.Data.Scanl.incrSum instead" #-} sum :: (Monad m, Num a) => Fold m (a, Maybe a) a sum = Window.windowSum --- {-# DEPRECATED sumInt "Use Streamly.Data.Fold.windowSumInt instead" #-} +{-# DEPRECATED sumInt "Use Streamly.Internal.Data.Scanl.incrSumInt instead" #-} sumInt :: (Monad m, Integral a) => Fold m (a, Maybe a) a sumInt = Window.windowSumInt --- {-# DEPRECATED powerSum "Use Streamly.Data.Fold.windowPowerSum instead" #-} +{-# DEPRECATED powerSum "Use Streamly.Internal.Data.Scanl.incrPowerSum instead" #-} powerSum :: (Monad m, Num a) => Int -> Fold m (a, Maybe a) a powerSum = Window.windowPowerSum @@ -369,6 +324,7 @@ fft marr -- /Time/: \(\mathcal{O}(n*w)\) where \(w\) is the window size. -- {-# INLINE minimum #-} +{-# DEPRECATED minimum "Use Streamly.Statistics.Scanl.incrMinimum instead" #-} minimum :: (Monad m, Ord a) => Fold m (a, Maybe a) a minimum = Fold step initial extract extract @@ -429,6 +385,7 @@ minimum = Fold step initial extract extract -- /Time/: \(\mathcal{O}(n*w)\) where \(w\) is the window size. -- {-# INLINE maximum #-} +{-# DEPRECATED maximum "Use Streamly.Statistics.Scanl.incrMaximum instead" #-} maximum :: (Monad m, Ord a) => Fold m (a, Maybe a) a maximum = Fold step initial extract extract @@ -501,6 +458,7 @@ maximum = Fold step initial extract extract -- -- /Time/: \(\mathcal{O}(n)\) {-# INLINE mean #-} +{-# DEPRECATED mean "Use Streamly.Internal.Data.Scanl.incrMean instead" #-} mean :: forall m a. (Monad m, Fractional a) => Fold m (a, Maybe a) a mean = Window.windowMean @@ -543,6 +501,7 @@ meanReplace n oldMean oldItem newItem = -- -- /Internal/ {-# INLINE welfordMean #-} +{-# DEPRECATED welfordMean "Use Streamly.Statistics.Scanl.incrWelfordMean instead" #-} welfordMean :: forall m a. (Monad m, Fractional a) => Fold m (a, Maybe a) a welfordMean = Fold step initial extract extract @@ -584,6 +543,7 @@ welfordMean = Fold step initial extract extract -- -- /Time/: \(\mathcal{O}(n)\) {-# INLINE rawMoment #-} +{-# DEPRECATED rawMoment "Use Streamly.Statistics.Scanl.incrRawMoment instead" #-} rawMoment :: (Monad m, Fractional a) => Int -> Fold m (a, Maybe a) a rawMoment k = Fold.teeWith (/) (Window.windowPowerSum k) Window.windowLength @@ -593,6 +553,7 @@ rawMoment k = Fold.teeWith (/) (Window.windowPowerSum k) Window.windowLength -- >>> rawMomentFrac p = Fold.teeWith (/) (Fold.windowPowerSumFrac p) Fold.windowLength -- {-# INLINE rawMomentFrac #-} +{-# DEPRECATED rawMomentFrac "Use Streamly.Statistics.Scanl.incrRawMomentFrac instead" #-} rawMomentFrac :: (Monad m, Floating a) => a -> Fold m (a, Maybe a) a rawMomentFrac k = Fold.teeWith (/) (Window.windowPowerSumFrac k) Window.windowLength @@ -616,6 +577,7 @@ rawMomentFrac k = -- See https://en.wikipedia.org/wiki/Generalized_mean -- {-# INLINE powerMean #-} +{-# DEPRECATED powerMean "Use Streamly.Statistics.Scanl.incrPowerMean instead" #-} powerMean :: (Monad m, Floating a) => Int -> Fold m (a, Maybe a) a powerMean k = (** (1 / fromIntegral k)) <$> rawMoment k @@ -625,6 +587,7 @@ powerMean k = (** (1 / fromIntegral k)) <$> rawMoment k -- >>> powerMeanFrac k = (** (1 / k)) <$> rawMomentFrac k -- {-# INLINE powerMeanFrac #-} +{-# DEPRECATED powerMeanFrac "Use Streamly.Statistics.Scanl.incrPowerMeanFrac instead" #-} powerMeanFrac :: (Monad m, Floating a) => a -> Fold m (a, Maybe a) a powerMeanFrac k = (** (1 / k)) <$> rawMomentFrac k @@ -641,6 +604,7 @@ powerMeanFrac k = (** (1 / k)) <$> rawMomentFrac k -- See https://en.wikipedia.org/wiki/Harmonic_mean . -- {-# INLINE harmonicMean #-} +{-# DEPRECATED harmonicMean "Use Streamly.Statistics.Scanl.incrHarmonicMean instead" #-} harmonicMean :: (Monad m, Fractional a) => Fold m (a, Maybe a) a harmonicMean = Fold.teeWith (/) @@ -660,6 +624,7 @@ harmonicMean = -- -- See https://en.wikipedia.org/wiki/Geometric_mean . {-# INLINE geometricMean #-} +{-# DEPRECATED geometricMean "Use Streamly.Statistics.Scanl.incrGeometricMean instead" #-} geometricMean :: (Monad m, Floating a) => Fold m (a, Maybe a) a geometricMean = exp <$> Window.windowLmap log mean @@ -673,6 +638,7 @@ geometricMean = exp <$> Window.windowLmap log mean -- See https://en.wikipedia.org/wiki/Root_mean_square . -- {-# INLINE quadraticMean #-} +{-# DEPRECATED quadraticMean "Use Streamly.Statistics.Scanl.incrQuadraticMean instead" #-} quadraticMean :: (Monad m, Floating a) => Fold m (a, Maybe a) a quadraticMean = powerMean 2 @@ -712,6 +678,7 @@ ewmaStep k x0 x1 = (1 - k) * x0 + k * x1 -- See https://en.wikipedia.org/wiki/Exponential_smoothing -- {-# INLINE ewma #-} +{-# DEPRECATED ewma "Use Streamly.Statistics.Scanl.ewma instead" #-} ewma :: Monad m => Double -> Fold m Double Double ewma k = extract <$> Fold.foldl' step (Tuple' 0 1) @@ -743,6 +710,7 @@ ewmaAfterMean n k = -- This is significantly faster than 'ewmaAfterMean'. -- {-# INLINE ewmaRampUpSmoothing #-} +{-# DEPRECATED ewmaRampUpSmoothing "Use Streamly.Statistics.Scanl.ewmaRampUpSmoothing instead" #-} ewmaRampUpSmoothing :: Monad m => Double -> Double -> Fold m Double Double ewmaRampUpSmoothing n k1 = extract <$> Fold.foldl' step initial @@ -773,6 +741,7 @@ ewmaRampUpSmoothing n k1 = extract <$> Fold.foldl' step initial -- /Time/: \(\mathcal{O}(n*w)\) where \(w\) is the window size. -- {-# INLINE range #-} +{-# DEPRECATED range "Use Streamly.Statistics.Scanl.incrRange instead" #-} range :: (Monad m, Num a, Ord a) => Fold m (a, Maybe a) a range = Fold.teeWith (-) maximum minimum @@ -793,6 +762,7 @@ range = Fold.teeWith (-) maximum minimum -- -- /Pre-release/ {-# INLINE md #-} +{-# DEPRECATED md "Use Streamly.Statistics.Scanl.incrMd instead" #-} md :: MonadIO m => Fold m ((Double, Maybe Double), m (MA.MutArray Double)) Double md = Fold.rmapM computeMD @@ -828,6 +798,7 @@ md = -- -- /Time/: \(\mathcal{O}(n)\) {-# INLINE variance #-} +{-# DEPRECATED variance "Use Streamly.Statistics.Scanl.incrVariance instead" #-} variance :: (Monad m, Fractional a) => Fold m (a, Maybe a) a variance = Fold.teeWith (\p2 m -> p2 - m ^ (2 :: Int)) (rawMoment 2) mean @@ -844,6 +815,7 @@ variance = Fold.teeWith (\p2 m -> p2 - m ^ (2 :: Int)) (rawMoment 2) mean -- -- /Time/: \(\mathcal{O}(n)\) {-# INLINE stdDev #-} +{-# DEPRECATED stdDev "Use Streamly.Statistics.Scanl.incrStdDev instead" #-} stdDev :: (Monad m, Floating a) => Fold m (a, Maybe a) a stdDev = sqrt <$> variance @@ -870,6 +842,7 @@ stdDev = sqrt <$> variance -- See https://en.wikipedia.org/wiki/Skewness . -- {-# INLINE skewness #-} +{-# DEPRECATED skewness "Use Streamly.Statistics.Scanl.incrSkewness instead" #-} skewness :: (Monad m, Floating a) => Fold m (a, Maybe a) a skewness = unTee @@ -906,6 +879,7 @@ skewness = -- See https://en.wikipedia.org/wiki/Kurtosis . -- {-# INLINE kurtosis #-} +{-# DEPRECATED kurtosis "Use Streamly.Statistics.Scanl.incrKurtosis instead" #-} kurtosis :: (Monad m, Floating a) => Fold m (a, Maybe a) a kurtosis = unTee @@ -934,6 +908,7 @@ kurtosis = -- See https://en.wikipedia.org/wiki/Bessel%27s_correction. -- {-# INLINE sampleVariance #-} +{-# DEPRECATED sampleVariance "Use Streamly.Statistics.Scanl.incrSampleVariance instead" #-} sampleVariance :: (Monad m, Fractional a) => Fold m (a, Maybe a) a sampleVariance = Fold.teeWith (\n s2 -> n * s2 / (n - 1)) Window.windowLength variance @@ -948,6 +923,7 @@ sampleVariance = -- . -- {-# INLINE sampleStdDev #-} +{-# DEPRECATED sampleStdDev "Use Streamly.Statistics.Scanl.incrSampleStdDev instead" #-} sampleStdDev :: (Monad m, Floating a) => Fold m (a, Maybe a) a sampleStdDev = sqrt <$> sampleVariance @@ -961,6 +937,7 @@ sampleStdDev = sqrt <$> sampleVariance -- -- /Time/: \(\mathcal{O}(n)\) {-# INLINE stdErrMean #-} +{-# DEPRECATED stdErrMean "Use Streamly.Statistics.Scanl.incrStdErrMean instead" #-} stdErrMean :: (Monad m, Floating a) => Fold m (a, Maybe a) a stdErrMean = Fold.teeWith (\sd n -> sd / sqrt n) sampleStdDev Window.windowLength @@ -1064,6 +1041,7 @@ foldResamples n arr fld = -- fromList [(1,1),(3,1),(4,2)] -- {-# INLINE frequency #-} +{-# DEPRECATED frequency "Use Streamly.Statistics.Scanl.incrFrequency instead" #-} frequency :: (Monad m, Ord a) => Fold m (a, Maybe a) (Map a Int) frequency = Fold.foldl' step Map.empty diff --git a/src/Streamly/Statistics/Scanl.hs b/src/Streamly/Statistics/Scanl.hs index 10983ba..3698403 100644 --- a/src/Streamly/Statistics/Scanl.hs +++ b/src/Streamly/Statistics/Scanl.hs @@ -7,25 +7,21 @@ -- Portability : GHC -- -- See "Streamly.Statistics" for general information. This module provides --- scans instead of folds. +-- composable incremental scans which can be used to efficiently compute online +-- statistics in rolling or sliding windows, or cumulative statistics over the +-- entire stream as well. {-# LANGUAGE ScopedTypeVariables #-} module Streamly.Statistics.Scanl ( -- * Incremental Scans - -- | Scans of type @Scanl m (a, Maybe a) b@ are incremental sliding window - -- scans. An input of type @(a, Nothing)@ indicates that the input element - -- @a@ is being inserted in the window without ejecting an old value - -- increasing the window size by 1. An input of type @(a, Just a)@ - -- indicates that the first element is being inserted in the window and the - -- second element is being removed from the window, the window size remains - -- the same. The window size can only increase and never decrease. + -- | Scans of type @Scanl m (Incr a) b@ are incremental sliding window + -- scans. -- - -- You can compute the statistics over the entire stream using sliding - -- window folds by keeping the second element of the input tuple as - -- @Nothing@. - -- - -- Also see "Streamly.Data.Scanl" for some basic window scans. + -- See "Streamly.Internal.Data.Scanl" for more details, especially the + -- documentation of 'Incr' type and 'incrScan' and 'cumulativeScan' + -- functions. Additional incremental scans can also be found in that + -- module. -- * Summary Statistics -- | See https://en.wikipedia.org/wiki/Summary_statistics . From 1af66d436e255026309da20bd5c6acf855e3742b Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 15 Jun 2026 17:16:55 +0530 Subject: [PATCH 4/7] Remove deprecated fold benchmarks --- benchmark/Main.hs | 162 +++---------------------------------- src/Streamly/Statistics.hs | 3 + streamly-statistics.cabal | 1 - 3 files changed, 12 insertions(+), 154 deletions(-) diff --git a/benchmark/Main.hs b/benchmark/Main.hs index 176ba33..8a23416 100644 --- a/benchmark/Main.hs +++ b/benchmark/Main.hs @@ -7,7 +7,6 @@ import Streamly.Data.Stream (Stream) import System.Random (randomRIO) import qualified Streamly.Data.Fold as Fold -import qualified Streamly.Internal.Data.RingArray as Ring import qualified Streamly.Internal.Data.Scanl as Scanl import qualified Streamly.Data.Stream as Stream import qualified Streamly.Data.Array as Array @@ -46,10 +45,6 @@ benchWith src len name f = benchWithFold :: Int -> String -> Fold IO Double Double -> Benchmark benchWithFold len name f = benchWith source len name f -{-# INLINE benchWithFoldInt #-} -benchWithFoldInt :: Int -> String -> Fold IO Int Int -> Benchmark -benchWithFoldInt len name f = benchWith source len name f - {-# INLINE benchWithScanSrc #-} benchWithScanSrc :: (Num a) => (Int -> a -> Stream IO a) -> Int -> String -> Scanl IO a a -> Benchmark @@ -84,152 +79,13 @@ benchWithFoldResamples len name f = bench name $ nfIO $ do numElements :: Int numElements = 100000 -mkBenchmarks :: +mkFolds :: (Int -> String -> Fold IO Double Double -> Benchmark) -> [Benchmark] -mkBenchmarks mkBench = +mkFolds mkBench = [ - mkBench numElements "minimum (window size 100)" - (Ring.slidingWindow 100 Statistics.minimum) - , mkBench numElements "minimum (window size 1000)" - (Ring.slidingWindow 1000 Statistics.minimum) - , benchWith sourceDescendingInt numElements - "minimum descending (window size 1000)" - (Ring.slidingWindow 1000 Statistics.minimum) - - , mkBench numElements "maximum (window size 100)" - (Ring.slidingWindow 100 Statistics.maximum) - , mkBench numElements "maximum (window size 1000)" - (Ring.slidingWindow 1000 Statistics.maximum) - , benchWith sourceDescendingInt numElements - "maximum descending (window size 1000)" - (Ring.slidingWindow 1000 Statistics.maximum) - - , mkBench numElements "range (window size 100)" - (Ring.slidingWindow 100 Statistics.range) - , mkBench numElements "range (window size 1000)" - (Ring.slidingWindow 1000 Statistics.range) - - , mkBench numElements "sum (window size 100)" - (Ring.slidingWindow 100 Statistics.sum) - , mkBench numElements "sum (window size 1000)" - (Ring.slidingWindow 1000 Statistics.sum) - , mkBench numElements "sum (entire stream)" - (Statistics.cumulative Statistics.sum) - , mkBench numElements "sum (Data.Fold)" Fold.sum - - , mkBench numElements "mean (window size 100)" - (Ring.slidingWindow 100 Statistics.mean) - , mkBench numElements "mean (window size 1000)" - (Ring.slidingWindow 1000 Statistics.mean) - , mkBench numElements "mean (entire stream)" - (Statistics.cumulative Statistics.mean) - , mkBench numElements "mean (Data.Fold)" Fold.mean - - , mkBench numElements "welfordMean (window size 100)" - (Ring.slidingWindow 100 Statistics.welfordMean) - , mkBench numElements "welfordMean (window size 1000)" - (Ring.slidingWindow 1000 Statistics.welfordMean) - , mkBench numElements "welfordMean (entire stream)" - (Statistics.cumulative Statistics.welfordMean) - - , mkBench numElements "geometricMean (window size 100)" - (Ring.slidingWindow 100 Statistics.geometricMean) - , mkBench numElements "geometricMean (window size 1000)" - (Ring.slidingWindow 1000 Statistics.geometricMean) - , mkBench numElements "geometricMean (entire stream)" - (Statistics.cumulative Statistics.geometricMean) - - , mkBench numElements "harmonicMean (window size 100)" - (Ring.slidingWindow 100 Statistics.harmonicMean) - , mkBench numElements "harmonicMean (window size 1000)" - (Ring.slidingWindow 1000 Statistics.harmonicMean) - , mkBench numElements "harmonicMean (entire stream)" - (Statistics.cumulative Statistics.harmonicMean) - - , mkBench numElements "quadraticMean (window size 100)" - (Ring.slidingWindow 100 Statistics.quadraticMean) - , mkBench numElements "quadraticMean (window size 1000)" - (Ring.slidingWindow 1000 Statistics.quadraticMean) - , mkBench numElements "quadraticMean (entire stream)" - (Statistics.cumulative Statistics.quadraticMean) - - , mkBench numElements "powerSum 2 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerSum 2)) - , mkBench numElements "powerSum 2 (entire stream)" - (Statistics.cumulative (Statistics.powerSum 2)) - - , mkBench numElements "rawMoment 2 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerSum 2)) - , mkBench numElements "rawMoment 2 (entire stream)" - (Statistics.cumulative (Statistics.rawMoment 2)) - - , mkBench numElements "powerMean 1 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerMean 1)) - , mkBench numElements "powerMean 2 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerMean 2)) - , mkBench numElements "powerMean 10 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerMean 10)) - - , mkBench numElements "powerMeanFrac (-1) (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerMeanFrac (-1))) - , mkBench numElements "powerMeanFrac 1 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerMeanFrac 1)) - , mkBench numElements "powerMeanFrac 2 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerMeanFrac 2)) - , mkBench numElements "powerMeanFrac 10 (window size 100)" - (Ring.slidingWindow 100 (Statistics.powerMeanFrac 10)) - - , mkBench numElements "ewma (entire stream)" - (Statistics.ewma 0.5) - , mkBench numElements "ewmaAfterMean (entire stream)" + mkBench numElements "ewmaAfterMean (entire stream)" (Statistics.ewmaAfterMean 10 0.5) - , mkBench numElements "ewmaRampUpSmoothing (entire stream)" - (Statistics.ewmaRampUpSmoothing 0.5 0.5) - - , mkBench numElements "variance (window size 100)" - (Ring.slidingWindow 100 Statistics.variance) - , mkBench numElements "variance (entire stream)" - (Statistics.cumulative Statistics.variance) - -- , mkBench numElements "variance (Data.Fold)" Fold.variance - - , mkBench numElements "sampleVariance (window size 100)" - (Ring.slidingWindow 100 Statistics.sampleVariance) - , mkBench numElements "sampleVariance (entire stream)" - (Statistics.cumulative Statistics.sampleVariance) - - , mkBench numElements "stdDev (window size 100)" - (Ring.slidingWindow 100 Statistics.stdDev) - , mkBench numElements "stdDev (entire stream)" - (Statistics.cumulative Statistics.stdDev) - -- , mkBench numElements "stdDev (Data.Fold)" Fold.stdDev - - , mkBench numElements "sampleStdDev (window size 100)" - (Ring.slidingWindow 100 Statistics.sampleStdDev) - , mkBench numElements "sampleStdDev (entire stream)" - (Statistics.cumulative Statistics.sampleStdDev) - - , mkBench numElements "stdErrMean (window size 100)" - (Ring.slidingWindow 100 Statistics.stdErrMean) - , mkBench numElements "stdErrMean (entire stream)" - (Statistics.cumulative Statistics.stdErrMean) - --- These benchmarks take a lot of time/memory with fusion-plugin possibly --- because of the use of Tee. -#ifndef FUSION_PLUGIN - , mkBench numElements "skewness (window size 100)" - (Ring.slidingWindow 100 Statistics.skewness) - , mkBench numElements "skewness (entire stream)" - (Statistics.cumulative Statistics.skewness) - - , mkBench numElements "kurtosis (window size 100)" - (Ring.slidingWindow 100 Statistics.kurtosis) - , mkBench numElements "kurtosis (entire stream)" - (Statistics.cumulative Statistics.kurtosis) -#endif - , mkBench numElements "md (window size 100)" - (Ring.slidingWindowWith 100 Statistics.md) - ] mkScans :: @@ -382,12 +238,12 @@ main :: IO () main = defaultMain [ - bgroup "fold" $ mkBenchmarks benchWithFold - , bgroup "fold_Int" - [ benchWithFoldInt numElements "sumInt (window size 100)" - (Ring.slidingWindow 100 Statistics.sumInt) - , benchWithFoldInt numElements "sum for Int (window size 100)" - (Ring.slidingWindow 100 Statistics.sum) + bgroup "fold" $ mkFolds benchWithFold + , bgroup "scan_Int" + [ benchWithScanSrc source numElements "sumInt (window size 100)" + (Scanl.incrScan 100 Scanl.incrSumInt :: Scanl IO Int Int) + , benchWithScanSrc source numElements "sum for Int (window size 100)" + (Scanl.incrScan 100 Scanl.incrSum :: Scanl IO Int Int) ] , bgroup "scan" $ mkScans benchWithPostscan -- XXX These benchmarks measure the cost of creating the array as well, diff --git a/src/Streamly/Statistics.hs b/src/Streamly/Statistics.hs index e16eabd..b41fac0 100644 --- a/src/Streamly/Statistics.hs +++ b/src/Streamly/Statistics.hs @@ -1,3 +1,6 @@ +-- We are re-exporting some deprecated functions. +{-# OPTIONS_GHC -Wno-deprecations #-} + -- | -- Module : Streamly.Statistics -- Copyright : (c) 2020 Composewell Technologies diff --git a/streamly-statistics.cabal b/streamly-statistics.cabal index f9e70ce..29d8002 100644 --- a/streamly-statistics.cabal +++ b/streamly-statistics.cabal @@ -94,7 +94,6 @@ common compile-options -Wincomplete-uni-patterns -Wredundant-constraints -Wnoncanonical-monad-instances - -Wno-deprecations -Rghc-timing common optimization-options From 31b4528f936480903388a8c6ecaa3f58b2c537ff Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 15 Jun 2026 17:34:50 +0530 Subject: [PATCH 5/7] Fix deprecation warnings in tests --- test/Main.hs | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/test/Main.hs b/test/Main.hs index 95ef8cb..9e52483 100644 --- a/test/Main.hs +++ b/test/Main.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE TupleSections #-} - import Control.Monad.IO.Class (liftIO) import Data.Complex (Complex ((:+))) import Data.Functor.Classes (liftEq2) @@ -18,7 +16,7 @@ import qualified Data.Vector as V import qualified Statistics.Sample.Powers as STAT import qualified Statistics.Transform as STAT import qualified Streamly.Data.Array as Array -import qualified Streamly.Data.Fold as Fold +import qualified Streamly.Internal.Data.Fold as Fold import qualified Streamly.Data.MutArray as MA import qualified Streamly.Internal.Data.RingArray as Ring import qualified Streamly.Data.Stream as Stream @@ -61,7 +59,7 @@ jackStdDevRes = testDistributions :: (STAT.Powers -> Double) - -> Fold.Fold IO (Double, Maybe Double) Double + -> Scanl.Scanl IO (Incr Double) Double -> Property testDistributions func fld = forAll (chooseInt (1, 1000)) $ \list_length -> @@ -71,22 +69,22 @@ testDistributions func fld = let var2 = func . STAT.powers 2 $ V.fromList ls strm = S.fromList ls var1 <- - liftIO $ S.fold (Ring.slidingWindow list_length fld) strm + liftIO $ S.fold (Fold.fromScanl (Scanl.incrScan list_length fld)) strm assert (validate $ abs (var1 - var2)) testVariance :: Property -testVariance = testDistributions STAT.variance variance +testVariance = testDistributions STAT.variance Stat.incrVariance testStdDev :: Property -testStdDev = testDistributions STAT.stdDev stdDev +testStdDev = testDistributions STAT.stdDev Stat.incrStdDev testFuncMD :: - Fold.Fold IO ((Double, Maybe Double), IO (MA.MutArray Double)) Double -> Spec + Scanl.Scanl IO (Incr Double, Ring.RingArray Double) Double -> Spec testFuncMD f = do let c = S.fromList [10.0, 11.0, 12.0, 14.0] - a1 <- runIO $ S.fold (Ring.slidingWindowWith 2 f) c - a2 <- runIO $ S.fold (Ring.slidingWindowWith 3 f) c - a3 <- runIO $ S.fold (Ring.slidingWindowWith 4 f) c + a1 <- runIO $ S.fold (Fold.fromScanl (Scanl.incrScanWith 2 f)) c + a2 <- runIO $ S.fold (Fold.fromScanl (Scanl.incrScanWith 3 f)) c + a3 <- runIO $ S.fold (Fold.fromScanl (Scanl.incrScanWith 4 f)) c it ("MD should be 1.0 , 1.1111111111111114 , 1.25 but actual is " ++ show a1 ++ " " ++ show a2 ++ " " ++ show a3) ( validate (abs (a1 - 1.0)) @@ -98,7 +96,7 @@ testFuncKurt :: Spec testFuncKurt = do let c = S.fromList [21.3 :: Double, 38.4, 12.7, 41.6] - krt <- runIO $ S.fold (Ring.slidingWindow 4 kurtosis) c + krt <- runIO $ S.fold (Fold.fromScanl (Scanl.incrScan 4 Stat.incrKurtosis)) c it ( "kurtosis should be 1.2762447351370185 Actual is " ++ show krt ) @@ -219,8 +217,8 @@ main = hspec $ do deviationLimit = 1 testFunc f = do let c = S.fromList input - a <- runIO $ S.fold (Ring.slidingWindow winSize f) c - b <- runIO $ S.fold f $ S.take winSize $ fmap (, Nothing) c + a <- runIO $ S.fold (Fold.fromScanl (Scanl.incrScan winSize f)) c + b <- runIO $ S.fold (Fold.fromScanl f) $ S.take winSize $ fmap Insert c let c1 = a - b it ("deviation " ++ show c1 ++ " should not be more than " ++ show deviationLimit @@ -229,9 +227,9 @@ main = hspec $ do ) $ c1 >= -1 * deviationLimit && c1 <= deviationLimit - describe "Sum" $ testFunc sum - describe "mean" $ testFunc mean - describe "welfordMean" $ testFunc welfordMean + describe "Sum" $ testFunc Scanl.incrSum + describe "mean" $ testFunc Scanl.incrMean + describe "welfordMean" $ testFunc Stat.incrWelfordMean describe "Correctness" $ do let winSize = 3 @@ -266,7 +264,7 @@ main = hspec $ do testFoldResamples 6 sampleList -- Spread/Mean - describe "MD" $ testFuncMD md + describe "MD" $ testFuncMD Stat.incrMd describe "Kurt" testFuncKurt prop "fft" testFFT describe "minimum" $ do From c3fd81e7eb663a5e0e48c69418ba3e4366f629db Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 15 Jun 2026 18:17:15 +0530 Subject: [PATCH 6/7] Fix docspec examples --- src/Streamly/Statistics.hs | 35 ++++++++++++++++++-------------- src/Streamly/Statistics/Scanl.hs | 30 +++++++++++++++------------ 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/Streamly/Statistics.hs b/src/Streamly/Statistics.hs index b41fac0..8feec2a 100644 --- a/src/Streamly/Statistics.hs +++ b/src/Streamly/Statistics.hs @@ -169,6 +169,11 @@ import qualified Streamly.Data.Stream as Stream import Prelude hiding (length, sum, minimum, maximum) +-- $setup +-- >>> :set -Wno-deprecations +-- >>> import qualified Streamly.Data.Stream as Stream +-- >>> import qualified Streamly.Internal.Data.RingArray as Ring + -- TODO: Overflow checks. Would be good if we can directly replace the -- operations with overflow checked operations. -- @@ -453,9 +458,9 @@ maximum = Fold step initial extract extract -- -- \(\mu = \mu'_1\) -- --- >>> mean = rawMoment 1 --- >>> mean = powerMean 1 --- >>> mean = Fold.teeWith (/) sum length +-- > mean = rawMoment 1 +-- > mean = powerMean 1 +-- > mean = Fold.teeWith (/) sum length -- -- /Space/: \(\mathcal{O}(1)\) -- @@ -538,7 +543,7 @@ welfordMean = Fold step initial extract extract -- -- \(\mu'_k = \frac{\sum_{i=1}^n x_{i}^k}{n}\) -- --- >>> rawMoment k = Fold.teeWith (/) (Fold.windowPowerSum p) Fold.windowLength +-- > rawMoment k = Fold.teeWith (/) (Fold.windowPowerSum p) Fold.windowLength -- -- See https://en.wikipedia.org/wiki/Moment_(mathematics) . -- @@ -553,7 +558,7 @@ rawMoment k = Fold.teeWith (/) (Window.windowPowerSum k) Window.windowLength -- | Like 'rawMoment' but powers can be negative or fractional. This is -- slower than 'rawMoment' for positive intergal powers. -- --- >>> rawMomentFrac p = Fold.teeWith (/) (Fold.windowPowerSumFrac p) Fold.windowLength +-- > rawMomentFrac p = Fold.teeWith (/) (Fold.windowPowerSumFrac p) Fold.windowLength -- {-# INLINE rawMomentFrac #-} {-# DEPRECATED rawMomentFrac "Use Streamly.Statistics.Scanl.incrRawMomentFrac instead" #-} @@ -572,7 +577,7 @@ rawMomentFrac k = -- -- \(powerMean(k) = (rawMoment(k))^\frac{1}{k}\) -- --- >>> powerMean k = (** (1 / fromIntegral k)) <$> rawMoment k +-- > powerMean k = (** (1 / fromIntegral k)) <$> rawMoment k -- -- All other means can be expressed in terms of power mean. It is also known as -- the generalized mean. @@ -587,7 +592,7 @@ powerMean k = (** (1 / fromIntegral k)) <$> rawMoment k -- | Like 'powerMean' but powers can be negative or fractional. This is -- slower than 'powerMean' for positive intergal powers. -- --- >>> powerMeanFrac k = (** (1 / k)) <$> rawMomentFrac k +-- > powerMeanFrac k = (** (1 / k)) <$> rawMomentFrac k -- {-# INLINE powerMeanFrac #-} {-# DEPRECATED powerMeanFrac "Use Streamly.Statistics.Scanl.incrPowerMeanFrac instead" #-} @@ -601,8 +606,8 @@ powerMeanFrac k = (** (1 / k)) <$> rawMomentFrac k -- -- \(HM = \left(\frac{\sum\limits_{i=1}^n x_i^{-1}}{n}\right)^{-1}\) -- --- >>> harmonicMean = Fold.teeWith (/) length (lmap recip sum) --- >>> harmonicMean = powerMeanFrac (-1) +-- > harmonicMean = Fold.teeWith (/) length (lmap recip sum) +-- > harmonicMean = powerMeanFrac (-1) -- -- See https://en.wikipedia.org/wiki/Harmonic_mean . -- @@ -623,7 +628,7 @@ harmonicMean = -- -- \(GM = e ^{{\frac{\sum_{i=1}^{n}\ln a_i}{n}}}\) -- --- >>> geometricMean = exp <$> lmap log mean +-- > geometricMean = exp <$> lmap log mean -- -- See https://en.wikipedia.org/wiki/Geometric_mean . {-# INLINE geometricMean #-} @@ -636,7 +641,7 @@ geometricMean = exp <$> Window.windowLmap log mean -- -- \(RMS = \sqrt{ \frac{1}{n} \left( x_1^2 + x_2^2 + \cdots + x_n^2 \right) }.\) -- --- >>> quadraticMean = powerMean 2 +-- > quadraticMean = powerMean 2 -- -- See https://en.wikipedia.org/wiki/Root_mean_square . -- @@ -734,7 +739,7 @@ ewmaRampUpSmoothing n k1 = extract <$> Fold.foldl' step initial -- | The difference between the maximum and minimum elements of a rolling window. -- --- >>> range = Fold.teeWith (-) maximum minimum +-- > range = Fold.teeWith (-) maximum minimum -- -- If you want to compute the range of the entire stream @Fold.teeWith (-) -- Fold.maximum Fold.minimum@ from the streamly package would be much faster. @@ -810,7 +815,7 @@ variance = Fold.teeWith (\p2 m -> p2 - m ^ (2 :: Int)) (rawMoment 2) mean -- This is the population standard deviation or uncorrected sample standard -- deviation. -- --- >>> stdDev = sqrt <$> variance +-- > stdDev = sqrt <$> variance -- -- See https://en.wikipedia.org/wiki/Standard_deviation . -- @@ -920,7 +925,7 @@ sampleVariance = -- -- \(s = \sqrt{sampleVariance}\) -- --- >>> sampleStdDev = sqrt <$> sampleVariance +-- > sampleStdDev = sqrt <$> sampleVariance -- -- See https://en.wikipedia.org/wiki/Unbiased_estimation_of_standard_deviation -- . @@ -1039,7 +1044,7 @@ foldResamples n arr fld = -- | Count the frequency of elements in a sliding window. -- -- >>> input = Stream.fromList [1,1,3,4,4::Int] --- >>> f = Ring.slidingWindow 4 Statistics.frequency +-- >>> f = Ring.slidingWindow 4 frequency -- >>> Stream.fold f input -- fromList [(1,1),(3,1),(4,2)] -- diff --git a/src/Streamly/Statistics/Scanl.hs b/src/Streamly/Statistics/Scanl.hs index 3698403..4ade184 100644 --- a/src/Streamly/Statistics/Scanl.hs +++ b/src/Streamly/Statistics/Scanl.hs @@ -106,6 +106,11 @@ import qualified Streamly.Data.Stream as Stream import Prelude hiding (length, sum, minimum, maximum) +-- $setup +-- >>> import qualified Streamly.Data.Stream as Stream +-- >>> import qualified Streamly.Internal.Data.Fold as Fold +-- >>> import qualified Streamly.Internal.Data.Scanl as Scanl + -- TODO: Overflow checks. Would be good if we can directly replace the -- operations with overflow checked operations. -- @@ -309,7 +314,7 @@ incrWelfordMean = Scanl step initial extract extract -- -- \(\mu'_k = \frac{\sum_{i=1}^n x_{i}^k}{n}\) -- --- >>> rawMoment k = Fold.teeWith (/) (Fold.windowPowerSum p) Fold.windowLength +-- >>> incrRawMoment k = Scanl.teeWith (/) (Scanl.incrPowerSum k) Scanl.incrCount -- -- See https://en.wikipedia.org/wiki/Moment_(mathematics) . -- @@ -324,7 +329,7 @@ incrRawMoment k = -- | Like 'rawMoment' but powers can be negative or fractional. This is -- slower than 'rawMoment' for positive intergal powers. -- --- >>> rawMomentFrac p = Fold.teeWith (/) (Fold.windowPowerSumFrac p) Fold.windowLength +-- >>> incrRawMomentFrac p = Scanl.teeWith (/) (Scanl.incrPowerSumFrac p) Scanl.incrCount -- {-# INLINE incrRawMomentFrac #-} incrRawMomentFrac :: (Monad m, Floating a) => a -> Scanl m (Incr a) a @@ -342,7 +347,7 @@ incrRawMomentFrac k = -- -- \(powerMean(k) = (rawMoment(k))^\frac{1}{k}\) -- --- >>> powerMean k = (** (1 / fromIntegral k)) <$> rawMoment k +-- >>> incrPowerMean k = (** (1 / fromIntegral k)) <$> incrRawMoment k -- -- All other means can be expressed in terms of power mean. It is also known as -- the generalized mean. @@ -356,7 +361,7 @@ incrPowerMean k = (** (1 / fromIntegral k)) <$> incrRawMoment k -- | Like 'powerMean' but powers can be negative or fractional. This is -- slower than 'powerMean' for positive intergal powers. -- --- >>> powerMeanFrac k = (** (1 / k)) <$> rawMomentFrac k +-- >>> incrPowerMeanFrac k = (** (1 / k)) <$> incrRawMomentFrac k -- {-# INLINE incrPowerMeanFrac #-} incrPowerMeanFrac :: (Monad m, Floating a) => a -> Scanl m (Incr a) a @@ -369,8 +374,8 @@ incrPowerMeanFrac k = (** (1 / k)) <$> incrRawMomentFrac k -- -- \(HM = \left(\frac{\sum\limits_{i=1}^n x_i^{-1}}{n}\right)^{-1}\) -- --- >>> harmonicMean = Fold.teeWith (/) length (lmap recip sum) --- >>> harmonicMean = powerMeanFrac (-1) +-- >>> incrHarmonicMean = Scanl.teeWith (/) Scanl.incrCount (Scanl.lmap (fmap recip) Scanl.incrSum) +-- >>> incrHarmonicMean = incrPowerMeanFrac (-1) -- -- See https://en.wikipedia.org/wiki/Harmonic_mean . -- @@ -390,7 +395,7 @@ incrHarmonicMean = -- -- \(GM = e ^{{\frac{\sum_{i=1}^{n}\ln a_i}{n}}}\) -- --- >>> geometricMean = exp <$> lmap log mean +-- >>> incrGeometricMean = exp <$> Scanl.lmap (fmap log) Scanl.incrMean -- -- See https://en.wikipedia.org/wiki/Geometric_mean . {-# INLINE incrGeometricMean #-} @@ -402,7 +407,7 @@ incrGeometricMean = exp <$> Scanl.lmap (fmap log) Scanl.incrMean -- -- \(RMS = \sqrt{ \frac{1}{n} \left( x_1^2 + x_2^2 + \cdots + x_n^2 \right) }.\) -- --- >>> quadraticMean = powerMean 2 +-- >>> incrQuadraticMean = incrPowerMean 2 -- -- See https://en.wikipedia.org/wiki/Root_mean_square . -- @@ -541,7 +546,7 @@ incrEwma w = Scanl step initial extract extract -- | The difference between the maximum and minimum elements of a rolling window. -- --- >>> range = Fold.teeWith (-) maximum minimum +-- >>> incrRange = Scanl.teeWith (-) incrMaximum incrMinimum -- -- If you want to compute the range of the entire stream @Fold.teeWith (-) -- Fold.maximum Fold.minimum@ from the streamly package would be much faster. @@ -620,7 +625,7 @@ incrVariance = -- This is the population standard deviation or uncorrected sample standard -- deviation. -- --- >>> stdDev = sqrt <$> variance +-- >>> incrStdDev = sqrt <$> incrVariance -- -- See https://en.wikipedia.org/wiki/Standard_deviation . -- @@ -727,7 +732,7 @@ incrSampleVariance = -- -- \(s = \sqrt{sampleVariance}\) -- --- >>> sampleStdDev = sqrt <$> sampleVariance +-- >>> incrSampleStdDev = sqrt <$> incrSampleVariance -- -- See https://en.wikipedia.org/wiki/Unbiased_estimation_of_standard_deviation -- . @@ -760,8 +765,7 @@ incrStdErrMean = -- | Count the frequency of elements in a sliding window. -- -- >>> input = Stream.fromList [1,1,3,4,4::Int] --- >>> f = Ring.slidingWindow 4 Statistics.frequency --- >>> Stream.fold f input +-- >>> Stream.fold (Fold.fromScanl (Scanl.incrScan 4 incrFrequency)) input -- fromList [(1,1),(3,1),(4,2)] -- {-# INLINE incrFrequency #-} From 3b5acba068368a980550317202d162f1f48b15ed Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 15 Jun 2026 18:24:48 +0530 Subject: [PATCH 7/7] Fix hlint warnings --- src/Streamly/Statistics.hs | 15 +++++++-------- src/Streamly/Statistics/Scanl.hs | 3 +-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Streamly/Statistics.hs b/src/Streamly/Statistics.hs index 8feec2a..aa9a17f 100644 --- a/src/Streamly/Statistics.hs +++ b/src/Streamly/Statistics.hs @@ -224,7 +224,7 @@ isPower2 n = n .&. (n - 1) == 0 -- {-# INLINE _power2 #-} _power2 :: Int -> Int -_power2 n = shiftL 1 n +_power2 = shiftL 1 -- | Create a bit mask with lower n bits 0 and the rest as 1. -- @@ -291,7 +291,7 @@ fft marr | l == log2len = return () | otherwise = do let !l2 = twice l1 - !e = -6.283185307179586/fromIntegral l2 + !e = -(6.283185307179586/fromIntegral l2) flight j !a | j == l1 = stage (l + 1) l2 | otherwise = do let butterfly i | i >= len = flight (j + 1) (a + e) @@ -710,7 +710,7 @@ ewma k = extract <$> Fold.foldl' step (Tuple' 0 1) {-# INLINE ewmaAfterMean #-} ewmaAfterMean :: Monad m => Int -> Double -> Fold m Double Double ewmaAfterMean n k = - Fold.concatMap (\i -> (Fold.foldl' (ewmaStep k) i)) (Fold.take n Fold.mean) + Fold.concatMap (Fold.foldl' (ewmaStep k)) (Fold.take n Fold.mean) -- | @ewma n k@ is like 'ewma' but uses 1 as the initial smoothing factor and -- then exponentially smooths it to @k@ using @n@ as the smoothing factor. @@ -783,8 +783,7 @@ md = Just action -> do arr <- action Stream.fold Fold.mean - $ fmap (\a -> abs (mn - a)) - $ Stream.unfold MA.reader arr + $ (\a -> abs (mn - a)) <$> Stream.unfold MA.reader arr Nothing -> return 0.0 -- | The variance \(\sigma^2\) of a population of \(n\) equally likely values @@ -970,7 +969,7 @@ jackKnifeMean :: (Monad m, Fractional a, Unbox a) => Array a -> Stream m a jackKnifeMean arr = do let len = fromIntegral (Array.length arr - 1) s = foldArray Fold.sum arr - in fmap (\b -> (s - b) / len) $ Array.read arr + in (\b -> (s - b) / len) <$> Array.read arr -- | Given an array of @n@ items, compute variance of @(n - 1)@ items at a time, -- producing a stream of all possible variance values omitting a different item @@ -984,7 +983,7 @@ jackKnifeVariance arr = do foldSums (s, s2) x = (s + x, s2 + x ^ (2 :: Int)) (sum1, sum2) = foldArray (Fold.foldl' foldSums (0.0, 0.0)) arr var x = (sum2 - x ^ (2 :: Int)) / len - ((sum1 - x) / len) ^ (2::Int) - in fmap var $ Array.read arr + in var <$> Array.read arr -- | Standard deviation computed from 'jackKnifeVariance'. -- @@ -1006,7 +1005,7 @@ resample = Unfold step inject inject arr = liftIO $ do g <- createSystemRandom - return $ (g, arr, Array.length arr, 0) + return (g, arr, Array.length arr, 0) chooseOne g arr len = do i <- uniformRM (0, len - 1) g diff --git a/src/Streamly/Statistics/Scanl.hs b/src/Streamly/Statistics/Scanl.hs index 4ade184..fb6c2a4 100644 --- a/src/Streamly/Statistics/Scanl.hs +++ b/src/Streamly/Statistics/Scanl.hs @@ -592,8 +592,7 @@ incrMd = case mRng of Just rng -> do Stream.fold Fold.mean - $ fmap (\a -> abs (mn - a)) - $ Ring.read rng + $ (\a -> abs (mn - a)) <$> Ring.read rng Nothing -> return 0.0 -- | The variance \(\sigma^2\) of a population of \(n\) equally likely values