on master help sign in
update docs, hide "duplicate"
f66ed7bHarendra Kumar
src/Streamly/Fold.hs+43−39
@@ -15,37 +15,39 @@
15-- Stability : experimental
15-- Stability : experimental
16-- Portability : GHC
16-- Portability : GHC
17--
17--
18−-- This module is the consumer side dual of the "Streamly.Prelude" module. The
18+-- A left fold consumes a stream and reduces it to a single value. Using the
19−-- "Streamly.Prelude" module contains producer or stream generation side
19+-- fold combinators in "Streamly.Prelude" module only one fold operation can be
20−-- compositions while this module contains consumer side or stream fold
20+-- applied to a stream. This module provides a 'Fold' type that represents a
21−-- composition. Both the modules are organized in the same way so that you can
21+-- left fold. Multiple such folds can be combined in different ways; a stream
22−-- easily find the corresponding operations.
22+-- can then be supplied to the combined fold.
23−--
24−-- Stream consumers are essentially left folds that can be composed in many
25−-- interesting ways. For example, a parsing applicative composition builds an
26−-- applicative parser, a distributing applicative fold composition distributes
23+-- For example, a distributive applicative composition distributes the input to
27−-- the input to the constituent folds and then combines the outputs.
24+-- the constituent folds and then combines the fold outputs. Similarly, a
28−-- Similarly, a partitioning applicative can partition the input among the
25+-- partitioning composition can partition the input among constituent folds.
29−-- constituent folds. There are many other ways to combine folds.
30−--
31−-- All combinators in this module are of true streaming nature. For example,
26+-- All the combinators in this module are of true streaming nature, stream
32−-- the splitting combinators accept a fold which consumes the elements in the
33−-- split segments as soon as they are generated by the producer, segments are
34−-- not buffered in memory, resulting in constant memory usage. The folds used
27+-- elements are not unnecessarily buffered in memory, guaranteeing a constant
35−-- in these combinators can be considered as continuations.
28+-- memory consumption.
29+--
30+-- Consider this module as the consumer side dual of the "Streamly.Prelude"
31+-- module. "Streamly.Prelude" provides combinators that can combine stream
32+-- sources in interesting ways whereas this module provides combinators that
33+-- combine stream consumers in interesting ways. In other words,
34+-- "Streamly.Prelude" provides stream merging capabilities while
35+-- "Streamly.Fold" provides stream splitting capabilities. Both the modules
36+-- are organized in the same way so that you can easily find the corresponding
37+-- operations.
36--
38--
37-- > import qualified Streamly.Fold as FL
39-- > import qualified Streamly.Fold as FL
38--
40--
39−--
40-- A left fold is represented by the type 'Fold'. @Fold m a b@ folds an
41-- A left fold is represented by the type 'Fold'. @Fold m a b@ folds an
41-- input stream consisting of values of type @a@ to a structure of type
42-- input stream consisting of values of type @a@ to a structure of type
42−-- @b@. The fold can be run using 'foldl'' and an input stream.
43+-- @b@. The fold can be run using the 'foldl'' combinator and an input stream.
43--
44--
44-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
45-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
45-- 5050
46-- 5050
46
47
47-- Also see the "Streamly.Sink" module that provides specialized left folds
48-- Also see the "Streamly.Sink" module that provides specialized left folds
48-- that discard the outputs.
49-- that discard the outputs.
50+--
49-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
51-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
50
52
51module Streamly.Fold
53module Streamly.Fold
@@ -84,7 +86,8 @@ module Streamly.Fold
84
86
85 -- ** Full Folds (To Containers)
87 -- ** Full Folds (To Containers)
86 -- | Avoid using these folds in scalable or performance critical
88 -- | Avoid using these folds in scalable or performance critical
87− -- applications, they buffer all the input in memory.
89+ -- applications, they buffer all the input in GC memory which can be
90+ -- detrimental to performance if the input is large.
88
91
89 , toStream -- experimental
92 , toStream -- experimental
90 , toStreamRev -- experimental
93 , toStreamRev -- experimental
@@ -318,7 +321,7 @@ module Streamly.Fold
318 -- * Nested Folds
321 -- * Nested Folds
319 -- , concatMap
322 -- , concatMap
320 -- , chunksOf
323 -- , chunksOf
321− , duplicate -- experimental
324+ -- , duplicate -- experimental
322
325
323 {-
326 {-
324 -- * Windowed Classification
327 -- * Windowed Classification
@@ -467,8 +470,7 @@ foldl' (Fold step begin done) = P.foldlMx' step begin done
467-- Transformations on fold inputs
470-- Transformations on fold inputs
468------------------------------------------------------------------------------
471------------------------------------------------------------------------------
469
472
470−-- | Convert a fold that generates a monadic action to a fold that generates
473+-- | Flatten the monadic output of a fold to pure output.
471−-- the output of that monadic action.
472--
474--
473-- @since 0.7.0
475-- @since 0.7.0
474{-# INLINE sequence #-}
476{-# INLINE sequence #-}
@@ -479,8 +481,7 @@ sequence (Fold step initial extract) = Fold step initial extract'
479 act <- extract x
481 act <- extract x
480 act >>= return
482 act >>= return
481
483
482−-- | Convert a fold that generates a monadic action to a fold that generates
484+-- | Map a monadic function on the output of a fold.
483−-- the output of that monadic action.
484--
485--
485-- @since 0.7.0
486-- @since 0.7.0
486{-# INLINE mapM #-}
487{-# INLINE mapM #-}
@@ -588,6 +589,8 @@ drain = Fold step begin done
588--
589--
589-- Drain all input after passing it through a monadic function. This is the
590-- Drain all input after passing it through a monadic function. This is the
590-- dual of mapM_ on stream producers.
591-- dual of mapM_ on stream producers.
592+--
593+-- @since 0.7.0
591{-# INLINABLE drainBy #-}
594{-# INLINABLE drainBy #-}
592drainBy :: Monad m => (a -> m b) -> Fold m a ()
595drainBy :: Monad m => (a -> m b) -> Fold m a ()
593drainBy f = Fold (const (void . f)) (return ()) return
596drainBy f = Fold (const (void . f)) (return ()) return
@@ -663,6 +666,8 @@ maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
663maximum = _Fold1 max
666maximum = _Fold1 max
664
667
665-- | Computes the minimum element with respect to the given comparison function
668-- | Computes the minimum element with respect to the given comparison function
669+--
670+-- @since 0.7.0
666{-# INLINABLE minimumBy #-}
671{-# INLINABLE minimumBy #-}
667minimumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
672minimumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
668minimumBy cmp = _Fold1 min'
673minimumBy cmp = _Fold1 min'
@@ -1080,8 +1085,8 @@ ltakeWhile predicate (Fold step initial done) = Fold step' initial' done'
1080--
1085--
1081
1086
1082-- | @splitAt n f1 f2@ composes folds @f1@ and @f2@ such that first @n@
1087-- | @splitAt n f1 f2@ composes folds @f1@ and @f2@ such that first @n@
1083−-- elements of its input are sent to fold @f1@ and the rest of the stream is
1088+-- elements of its input are consumed by fold @f1@ and the rest of the stream
1084−-- sent to fold @f2@.
1089+-- is consumed by fold @f2@.
1085--
1090--
1086-- > let splitAt_ n xs = FL.foldl' (FL.splitAt n FL.toList FL.toList) $ S.fromList xs
1091-- > let splitAt_ n xs = FL.foldl' (FL.splitAt n FL.toList FL.toList) $ S.fromList xs
1087--
1092--
@@ -1248,10 +1253,9 @@ _spanBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1248
1253
1249 extract (Tuple3' a b _) = (,) <$> extractL a <*> extractR b
1254 extract (Tuple3' a b _) = (,) <$> extractL a <*> extractR b
1250
1255
1251−-- | Span as long as the predicate is 'True'. @span p f1 f2@ composes folds
1256+-- | @span p f1 f2@ composes folds @f1@ and @f2@ such that @f1@ consumes the
1252−-- @f1@ and @f2@ such that the composed fold continues sending the input to
1253−-- @f1@ as long as the predicate @p@ is 'True'. The rest of the input is sent
1257+-- input as long as the predicate @p@ is 'True'. @f2@ consumes the rest of the
1254−-- to @f2@.
1258+-- input.
1255--
1259--
1256-- > let span_ p xs = FL.foldl' (FL.span p FL.toList FL.toList) $ S.fromList xs
1260-- > let span_ p xs = FL.foldl' (FL.span p FL.toList FL.toList) $ S.fromList xs
1257--
1261--
@@ -1264,10 +1268,10 @@ _spanBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1264-- >>> span_ (< 4) [1,2,3]
1268-- >>> span_ (< 4) [1,2,3]
1265-- > ([1,2,3],[])
1269-- > ([1,2,3],[])
1266--
1270--
1271+-- @since 0.7.0
1272+
1267-- This can be considered as a two-fold version of 'ltakeWhile' where we take
1273-- This can be considered as a two-fold version of 'ltakeWhile' where we take
1268-- both the segments instead of discarding the leftover.
1274-- both the segments instead of discarding the leftover.
1269−--
1270−-- @since 0.7.0
1271{-# INLINE span #-}
1275{-# INLINE span #-}
1272span
1276span
1273 :: Monad m
1277 :: Monad m
@@ -1292,8 +1296,8 @@ span p (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1292-- > break p = span (not . p)
1296-- > break p = span (not . p)
1293--
1297--
1294-- Break as soon as the predicate becomes 'True'. @break p f1 f2@ composes
1298-- Break as soon as the predicate becomes 'True'. @break p f1 f2@ composes
1295−-- folds @f1@ and @f2@ such that @f1@ stops receiving input as soon as the
1299+-- folds @f1@ and @f2@ such that @f1@ stops consuming input as soon as the
1296−-- predicate @p@ becomes 'True'. The rest of the input is sent to @f2@.
1300+-- predicate @p@ becomes 'True'. The rest of the input is consumed @f2@.
1297--
1301--
1298-- This is the binary version of 'splitBy'.
1302-- This is the binary version of 'splitBy'.
1299--
1303--
@@ -2244,9 +2248,9 @@ unzip = unzipWith id
2244-- > 465
2248-- > 465
2245--
2249--
2246-- @since 0.7.0
2250-- @since 0.7.0
2247−{-# INLINABLE duplicate #-}
2251+{-# INLINABLE _duplicate #-}
2248−duplicate :: Applicative m => Fold m a b -> Fold m a (Fold m a b)
2252+_duplicate :: Applicative m => Fold m a b -> Fold m a (Fold m a b)
2249−duplicate (Fold step begin done) =
2253+_duplicate (Fold step begin done) =
2250 Fold step begin (\x -> pure (Fold step (pure x) done))
2254 Fold step begin (\x -> pure (Fold step (pure x) done))
2251
2255
2252{-
2256{-