on master help sign in
Add rollingHashFirstN, drainN and drainWhile
d6afd92adithyaov
benchmark/Linear.hs+3
@@ -229,6 +229,9 @@ main =
229 ]
229 ]
230 , bgroup "folds"
230 , bgroup "folds"
231 [ benchIOSink "drain" (S.fold FL.drain)
231 [ benchIOSink "drain" (S.fold FL.drain)
232+ , benchIOSink "drainN" (S.fold (IFL.drainN Ops.value))
233+ , benchIOSink "drainWhileTrue" (S.fold (IFL.drainWhile $ (<=) Ops.maxValue))
234+ , benchIOSink "drainWhileFalse" (S.fold (IFL.drainWhile $ (>=) Ops.maxValue))
232 , benchIOSink "sink" (S.fold $ Sink.toFold Sink.drain)
235 , benchIOSink "sink" (S.fold $ Sink.toFold Sink.drain)
233 , benchIOSink "last" (S.fold FL.last)
236 , benchIOSink "last" (S.fold FL.last)
234 , benchIOSink "length" (S.fold FL.length)
237 , benchIOSink "length" (S.fold FL.length)
src/Streamly/Internal/Data/Fold.hs+23−3
@@ -56,7 +56,7 @@ module Streamly.Internal.Data.Fold
56 , stdDev
56 , stdDev
57 , rollingHash
57 , rollingHash
58 , rollingHashWithSalt
58 , rollingHashWithSalt
59− -- , rollingHashFirstN
59+ , rollingHashFirstN
60 -- , rollingHashLastN
60 -- , rollingHashLastN
61
61
62 -- ** Full Folds (Monoidal)
62 -- ** Full Folds (Monoidal)
@@ -70,8 +70,8 @@ module Streamly.Internal.Data.Fold
70 , toListRevF -- experimental
70 , toListRevF -- experimental
71
71
72 -- ** Partial Folds
72 -- ** Partial Folds
73− -- , drainN
73+ , drainN
74− -- , drainWhile
74+ , drainWhile
75 -- , lastN
75 -- , lastN
76 -- , (!!)
76 -- , (!!)
77 -- , genericIndex
77 -- , genericIndex
@@ -563,6 +563,14 @@ defaultSalt = 0x087fc72c
563rollingHash :: (Monad m, Enum a) => Fold m a Int
563rollingHash :: (Monad m, Enum a) => Fold m a Int
564rollingHash = rollingHashWithSalt defaultSalt
564rollingHash = rollingHashWithSalt defaultSalt
565
565
566+-- | Compute an 'Int' sized polynomial rolling hash of the first n elements of
567+-- a stream.
568+--
569+-- > rollingHashFirstN = ltake n rollingHash
570+{-# INLINABLE rollingHashFirstN #-}
571+rollingHashFirstN :: (Monad m, Enum a) => Int -> Fold m a Int
572+rollingHashFirstN n = ltake n rollingHash
573+
566------------------------------------------------------------------------------
574------------------------------------------------------------------------------
567-- Monoidal left folds
575-- Monoidal left folds
568------------------------------------------------------------------------------
576------------------------------------------------------------------------------
@@ -631,6 +639,18 @@ toList = Fold (\f x -> return $ f . (x :))
631-- Partial Folds
639-- Partial Folds
632------------------------------------------------------------------------------
640------------------------------------------------------------------------------
633
641
642+-- | A fold that drains the first n elements of its input, running the effects
643+-- and discarding the results.
644+{-# INLINABLE drainN #-}
645+drainN :: Monad m => Int -> Fold m a ()
646+drainN n = ltake n drain
647+
648+-- | A fold that drains elements of its input as long as the predicate succeeds,
649+-- running the effects and discarding the results.
650+{-# INLINABLE drainWhile #-}
651+drainWhile :: Monad m => (a -> Bool) -> Fold m a ()
652+drainWhile p = ltakeWhile p drain
653+
634------------------------------------------------------------------------------
654------------------------------------------------------------------------------
635-- To Elements
655-- To Elements
636------------------------------------------------------------------------------
656------------------------------------------------------------------------------
streamly.cabal+13
@@ -464,6 +464,19 @@ test-suite array-test
464 transformers >= 0.4 && < 0.6
464 transformers >= 0.4 && < 0.6
465 default-language: Haskell2010
465 default-language: Haskell2010
466
466
467+test-suite internal-data-fold-test
468+ import: test-options
469+ type: exitcode-stdio-1.0
470+ main-is: Streamly/Test/Internal/Data/Fold.hs
471+ js-sources: jsbits/clock.js
472+ hs-source-dirs: test
473+ build-depends:
474+ streamly
475+ , base >= 4.8 && < 5
476+ , hspec >= 2.0 && < 3
477+ , QuickCheck >= 2.10 && < 2.14
478+ default-language: Haskell2010
479+
467test-suite data-array-test
480test-suite data-array-test
468 import: test-options
481 import: test-options
469 type: exitcode-stdio-1.0
482 type: exitcode-stdio-1.0
test/Streamly/Test/Internal/Data/Fold.hsnew file+27
@@ -0,0 +1,27 @@
1+module Main (main) where
2+
3+import qualified Streamly.Prelude as S
4+import Streamly.Internal.Data.Fold
5+
6+import Test.Hspec.QuickCheck
7+import Test.QuickCheck (Property, forAll, Gen, vectorOf, arbitrary, choose)
8+import Test.QuickCheck.Monadic (monadicIO, assert, run)
9+
10+import Test.Hspec as H
11+
12+maxStreamLen :: Int
13+maxStreamLen = 1000
14+
15+testRollingHashFirstN :: Property
16+testRollingHashFirstN =
17+ forAll (choose (0, maxStreamLen)) $ \len ->
18+ forAll (choose (0, len)) $ \n ->
19+ forAll (vectorOf len (arbitrary :: Gen Int)) $ \vec -> monadicIO $ do
20+ a <- run $ S.fold rollingHash $ S.take n $ S.fromList vec
21+ b <- run $ S.fold (rollingHashFirstN n) $ S.fromList vec
22+ assert $ a == b
23+
24+main :: IO ()
25+main = hspec $
26+ describe "Rolling Hash Folds" $
27+ prop "testRollingHashFirstN" testRollingHashFirstN