@@ -35,7 +35,6 @@ module Streamly.Internal.Data.Fold.Window
37 , cumulative
37 , cumulative
40 -- ** Sums
39 -- ** Sums
@@ -49,6 +48,9 @@ module Streamly.Internal.Data.Fold.Window
@@ -66,10 +68,12 @@ import qualified Streamly.Internal.Data.Ring.Foreign as Ring
67import Prelude hiding (length, sum, minimum, maximum)
69import Prelude hiding (length, sum, minimum, maximum)
71-- >>> import Data.Bifunctor(bimap)
72-- >>> import Data.Bifunctor(bimap)
72-- >>> import qualified Streamly.Data.Fold as Fold
73-- >>> import qualified Streamly.Data.Fold as Fold
74+-- >>> import qualified Streamly.Internal.Data.Fold.Window as FoldW
75+-- >>> import qualified Streamly.Internal.Data.Ring.Foreign as Ring
76+-- >>> import qualified Streamly.Prelude as Stream
73-- >>> import Prelude hiding (length, sum, minimum, maximum)
77-- >>> import Prelude hiding (length, sum, minimum, maximum)
75-------------------------------------------------------------------------------
79-------------------------------------------------------------------------------
@@ -313,38 +317,35 @@ maximum n = fmap (fmap snd) $ range n
313mean :: forall m a. (Monad m, Fractional a) => Fold m (a, Maybe a) a
317mean :: forall m a. (Monad m, Fractional a) => Fold m (a, Maybe a) a
314mean = Fold.teeWith (/) sum length
318mean = Fold.teeWith (/) sum length
316−-- | Drop repeated elements within the specified
320+-------------------------------------------------------------------------------
317−-- tumbling window in the stream.
321+-- Distribution
318−-- /Pre-release/
322+-------------------------------------------------------------------------------
324+-- XXX We can use a Windowed classifyWith operation, that will allow us to
325+-- express windowed frequency, mode, histograms etc idiomatically.
327+-- | Count the frequency of elements in a sliding window.
320−-- >>> import qualified Streamly.Prelude as S
329+-- >>> input = Stream.fromList [1,1,3,4,4::Int]
321−-- >>> S.fold nub $ S.fromList [(1, Nothing), (1, Nothing), (3, Nothing), (4, Just 1)]
330+-- >>> f = Ring.slidingWindow 4 FoldW.frequency
331+-- >>> Stream.fold f input
322−-- fromList [(1,1),(3,1),(4,1)]
332+-- fromList [(1,1),(3,1),(4,2)]
324−{-# INLINE nub #-}
336+{-# INLINE frequency #-}
325−nub :: (Monad m, Ord a) => Fold m (a, Maybe a) (Map.Map a Int)
337+frequency :: (Monad m, Ord a) => Fold m (a, Maybe a) (Map.Map a Int)
326−nub = Fold step initial extract
338+frequency = Fold.foldl' step Map.empty
330− initial =
342+ decrement v =
331− return $ Partial Map.empty
333− updateRefCounts new map0 = return $ Map.insertWith (+) new (1::Int) map0
335− alter a m1 (Just v) =
336 if v == 1
343 if v == 1
338− _ <- return $ Map.delete a m1
339− return Nothing
344+ then Nothing
340− else return $ Just (v -1)
345+ else Just (v - 1)
341− alter _ _ Nothing = error "Invalid old element"
346+
343− step map0 (new, mOld) = do
347+ step refCountMap (new, mOld) =
344− m1 <- updateRefCounts new map0
348+ let m1 = Map.insertWith (+) new 1 refCountMap
346− case mOld of
349+ in case mOld of
347− Just a -> Map.alterF (alter a m1) a m1
350+ Just k -> Map.update decrement k m1
348− Nothing -> return m1
351+ Nothing -> m1