@@ -170,16 +170,18 @@ module Streamly.Prelude
170-- the previous step. However, it is possible to fold parts of the stream in
170-- the previous step. However, it is possible to fold parts of the stream in
171-- parallel and then combine the results using a monoid.
171-- parallel and then combine the results using a monoid.
179 , foldl1'
181 , foldl1'
180 , foldlM'
182 , foldlM'
182− -- * Running Folds
184+ -- ** Composable Left Folds
183 -- $runningfolds
185 -- $runningfolds
185 , runFold
187 , runFold
@@ -316,6 +318,7 @@ module Streamly.Prelude
316 -- > foldl f z xs = last $ scanl f z xs
318 -- > foldl f z xs = last $ scanl f z xs
317 -- > foldr f z xs = head $ scanr f z xs
319 -- > foldr f z xs = head $ scanr f z xs
320 , scanlM'
323 , scanlM'
321 , postscanl'
324 , postscanl'
@@ -325,7 +328,7 @@ module Streamly.Prelude
325 , scanl1'
328 , scanl1'
326 , scanl1M'
329 , scanl1M'
328− -- ** Running Scans
331+ -- ** Scan Using Fold
329 , runScan
332 , runScan
330 , runPostscan
333 , runPostscan
@@ -339,6 +342,7 @@ module Streamly.Prelude
339 -- , lprescanl'
342 -- , lprescanl'
340 -- , lprescanlM'
343 -- , lprescanlM'
342 , indexed
346 , indexed
343 , indexedR
347 , indexedR
344 -- , timestamped
348 -- , timestamped
@@ -460,7 +464,7 @@ module Streamly.Prelude
460 -- , interposeBy
464 -- , interposeBy
461 -- , intercalate
465 -- , intercalate
463− -- ** Breaking
467+ -- -- ** Breaking
465 -- By chunks
469 -- By chunks
466 -- , splitAt -- spanN
470 -- , splitAt -- spanN
@@ -490,14 +494,14 @@ module Streamly.Prelude
491 -- , groupScan
495 -- , groupScan
493− -- *** Chunks
497+ -- -- *** Chunks
494 , chunksOf
498 , chunksOf
495 , sessionsOf
499 , sessionsOf
497 -- , lchunksOf
501 -- , lchunksOf
498 -- , lsessionsOf
502 -- , lsessionsOf
500− -- *** Using Element Separators
504+ -- -- *** Using Element Separators
501 -- On == Dropping the separator
505 -- On == Dropping the separator
502 , splitOn
506 , splitOn
503 , splitOnSuffix
507 , splitOnSuffix
@@ -1346,19 +1350,20 @@ foldlM' step begin m = S.foldlM' step begin $ toStreamS m
1347-- $runningfolds
1351-- $runningfolds
1349−-- We can use the left folds in this module instead of the folds in
1353+-- "Streamly.Fold" module defines composable left folds which can be combined
1350−-- "Streamly.Prelude". For example the following two ways of folding are
1354+-- together in many interesting ways. Those folds can be run using 'runFold'.
1351−-- equivalent in functionality and performance,
1355+-- The following two ways of folding are equivalent in functionality and
1353−-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
1358+-- >>> S.runFold FL.sum (S.enumerateFromTo 1 100)
1355-- >>> S.sum (S.enumerateFromTo 1 100)
1360-- >>> S.sum (S.enumerateFromTo 1 100)
1358−-- However, left folds are push type folds. That means we push the entire input
1363+-- However, left folds cannot terminate early even if it does not need to
1359−-- to a fold before we can get the output. Therefore, the performance is
1364+-- consume more input to determine the result. Therefore, the performance is
1360-- equivalent only for full folds like 'sum' and 'length'. For partial folds
1365-- equivalent only for full folds like 'sum' and 'length'. For partial folds
1361−-- like 'head' or 'any' the folds in "Streamly.Prelude" may be much more
1366+-- like 'head' or 'any' the the folds defined in this module may be much more
1362-- efficient because they are implemented as right folds that terminate as soon
1367-- efficient because they are implemented as right folds that terminate as soon
1363-- as we get the result. Note that when a full fold is composed with a partial
1368-- as we get the result. Note that when a full fold is composed with a partial
1364-- fold in parallel the performance is not impacted as we anyway have to
1369-- fold in parallel the performance is not impacted as we anyway have to
@@ -1366,13 +1371,13 @@ foldlM' step begin m = S.foldlM' step begin $ toStreamS m
1367-- >>> S.head (1 `S.cons` undefined)
1372-- >>> S.head (1 `S.cons` undefined)
1368-- Just 1
1373-- Just 1
1369−-- >>> FL.foldl' FL.head (1 `S.cons` undefined)
1374+-- >>> S.runFold FL.head (1 `S.cons` undefined)
1370-- *** Exception: Prelude.undefined
1375-- *** Exception: Prelude.undefined
1372-- However, we can wrap the fold in a scan to convert it into a lazy stream of
1377-- However, we can wrap the fold in a scan to convert it into a lazy stream of
1373-- fold steps. We can then terminate the stream whenever we want. For example,
1378-- fold steps. We can then terminate the stream whenever we want. For example,
1375−-- >>> S.toList $ S.take 1 $ FL.scanl' FL.head (1 `S.cons` undefined)
1380+-- >>> S.toList $ S.take 1 $ S.runScan FL.head (1 `S.cons` undefined)
1376-- [Nothing]
1381-- [Nothing]
1378-- The following example extracts the input stream up to a point where the
1383-- The following example extracts the input stream up to a point where the
@@ -1382,15 +1387,15 @@ foldlM' step begin m = S.foldlM' step begin $ toStreamS m
1382-- > S.toList
1387-- > S.toList
1383-- $ S.map (fromJust . fst)
1388-- $ S.map (fromJust . fst)
1384-- $ S.takeWhile (\\(_,x) -> x <= 10)
1389-- $ S.takeWhile (\\(_,x) -> x <= 10)
1385−-- $ FL.postscanl' ((,) \<$> FL.last \<*> avg) (S.enumerateFromTo 1.0 100.0)
1390+-- $ S.runPostscan ((,) \<$> FL.last \<*> avg) (S.enumerateFromTo 1.0 100.0)
1388-- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
1393-- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
1391−-- | Fold a stream using the supplied monadic fold.
1396+-- | Fold a stream using the supplied left fold.
1393−-- >>> S.foldlStream FL.sum (S.enumerateFromTo 1 100)
1398+-- >>> S.runFold FL.sum (S.enumerateFromTo 1 100)
1396-- @since 0.7.0
1401-- @since 0.7.0
@@ -2181,15 +2186,15 @@ mapMaybeMSerial f m = fromStreamD $ D.mapMaybeM f $ toStreamD m
2181-- XXX Use a compact region list to temporarily store the list, in both reverse
2186-- XXX Use a compact region list to temporarily store the list, in both reverse
2182-- as well as in reverse'.
2187-- as well as in reverse'.
2189+-- /Note:/ 'reverse'' is much faster than this, use that when performance
2185-- > reverse = S.foldlT (flip S.cons) S.nil
2193-- > reverse = S.foldlT (flip S.cons) S.nil
2187-- Returns the elements of the stream in reverse order. The stream must be
2195-- Returns the elements of the stream in reverse order. The stream must be
2188-- finite. Note that this necessarily buffers the entire stream in memory.
2196-- finite. Note that this necessarily buffers the entire stream in memory.
2190−-- /Note:/ 'reverse'' is much faster than this, use that when performance
2193-- /Since 0.7.0 (Monad m constraint)/
2198-- /Since 0.7.0 (Monad m constraint)/
2195-- /Since: 0.1.1/
2200-- /Since: 0.1.1/
@@ -2567,7 +2572,7 @@ intercalate :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
2567-- elements of its input are consumed by fold @f1@ and the rest of the stream
2572-- elements of its input are consumed by fold @f1@ and the rest of the stream
2568-- is consumed by fold @f2@.
2573-- is consumed by fold @f2@.
2570−-- > let splitAt_ n xs = FL.foldl' (FL.splitAt n FL.toList FL.toList) $ S.fromList xs
2575+-- > let splitAt_ n xs = S.runFold (FL.splitAt n FL.toList FL.toList) $ S.fromList xs
2572-- >>> splitAt_ 6 "Hello World!"
2577-- >>> splitAt_ 6 "Hello World!"
2573-- > ("Hello ","World!")
2578-- > ("Hello ","World!")
@@ -2656,7 +2661,7 @@ groupScan split fold m = undefined
2656-- | Group the input stream into groups of @n@ elements each and then fold each
2661-- | Group the input stream into groups of @n@ elements each and then fold each
2657-- group using the provided fold function.
2662-- group using the provided fold function.
2659−-- >> S.toList $ FL.chunksOf 2 FL.sum (S.enumerateFromTo 1 10)
2664+-- >> S.toList $ S.chunksOf 2 FL.sum (S.enumerateFromTo 1 10)
2660-- > [3,7,11,15,19]
2665-- > [3,7,11,15,19]
2662-- This can be considered as an n-fold version of 'ltake' where we apply
2667-- This can be considered as an n-fold version of 'ltake' where we apply
@@ -2736,7 +2741,7 @@ _spanBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
2736-- input as long as the predicate @p@ is 'True'. @f2@ consumes the rest of the
2741-- input as long as the predicate @p@ is 'True'. @f2@ consumes the rest of the
2737-- input.
2742-- input.
2739−-- > let span_ p xs = FL.foldl' (FL.span p FL.toList FL.toList) $ S.fromList xs
2744+-- > let span_ p xs = S.runFold (S.span p FL.toList FL.toList) $ S.fromList xs
2741-- >>> span_ (< 1) [1,2,3]
2746-- >>> span_ (< 1) [1,2,3]
2742-- > ([],[1,2,3])
2747-- > ([],[1,2,3])
@@ -2781,7 +2786,7 @@ span p (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
2782-- This is the binary version of 'splitBy'.
2787-- This is the binary version of 'splitBy'.
2784−-- > let break_ p xs = FL.foldl' (FL.break p FL.toList FL.toList) $ S.fromList xs
2789+-- > let break_ p xs = S.runFold (S.break p FL.toList FL.toList) $ S.fromList xs
2786-- >>> break_ (< 1) [3,2,1]
2791-- >>> break_ (< 1) [3,2,1]
2787-- > ([3,2,1],[])
2792-- > ([3,2,1],[])
@@ -2838,7 +2843,7 @@ _spanRollingBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR)
2838-- group is folded using the fold @f@ and the result of the fold is emitted in
2843-- group is folded using the fold @f@ and the result of the fold is emitted in
2839-- the output stream.
2844-- the output stream.
2841−-- >>> S.toList $ FL.groupsBy (>) FL.toList $ S.fromList [1,3,7,0,2,5]
2846+-- >>> S.toList $ S.groupsBy (>) FL.toList $ S.fromList [1,3,7,0,2,5]
2842-- > [[1,3,7],[0,2,5]]
2847-- > [[1,3,7],[0,2,5]]
2844-- @since 0.7.0
2849-- @since 0.7.0
@@ -2859,7 +2864,7 @@ groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
2859-- comparison fails a new group is started. Each group is folded using the fold
2864-- comparison fails a new group is started. Each group is folded using the fold
2862−-- >>> S.toList $ FL.groupsByRolling (\a b -> a + 1 == b) FL.toList $ S.fromList [1,2,3,7,8,9]
2867+-- >>> S.toList $ S.groupsByRolling (\a b -> a + 1 == b) FL.toList $ S.fromList [1,2,3,7,8,9]
2863-- > [[1,2,3],[7,8,9]]
2868-- > [[1,2,3],[7,8,9]]
2865-- @since 0.7.0
2870-- @since 0.7.0
@@ -2878,7 +2883,7 @@ groupsByRolling cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD
2879-- Groups contiguous spans of equal elements together in individual groups.
2884-- Groups contiguous spans of equal elements together in individual groups.
2881−-- >>> S.toList $ FL.groups FL.toList $ S.fromList [1,1,2,2]
2886+-- >>> S.toList $ S.groups FL.toList $ S.fromList [1,1,2,2]
2882-- > [[1,1],[2,2]]
2887-- > [[1,1],[2,2]]
2884-- @since 0.7.0
2889-- @since 0.7.0
@@ -2895,7 +2900,7 @@ groups = groupsBy (==)
2895-- stream before the sequence and the second part consisting of the sequence
2900-- stream before the sequence and the second part consisting of the sequence
2896-- and the rest of the stream.
2901-- and the rest of the stream.
2898−-- > let breakOn_ pat xs = FL.foldl' (FL.breakOn pat FL.toList FL.toList) $ S.fromList xs
2903+-- > let breakOn_ pat xs = S.runFold (S.breakOn pat FL.toList FL.toList) $ S.fromList xs
2900-- >>> breakOn_ "dear" "Hello dear world!"
2905-- >>> breakOn_ "dear" "Hello dear world!"
2901-- > ("Hello ","dear world!")
2906-- > ("Hello ","dear world!")
@@ -2931,7 +2936,7 @@ breakOn pat f m = undefined
2932-- Let's use the following definition for illustration:
2937-- Let's use the following definition for illustration:
2934−-- > splitOn' p xs = S.toList $ FL.splitOn p (FL.toList) (S.fromList xs)
2939+-- > splitOn' p xs = S.toList $ S.splitOn p (FL.toList) (S.fromList xs)
2936-- >>> splitOn' (== '.') ""
2941-- >>> splitOn' (== '.') ""
@@ -2975,7 +2980,7 @@ splitOn predicate f m =
2975-- ".--." => "" "--"
2980-- ".--." => "" "--"
2978−-- > splitOnSuffix' p xs = S.toList $ FL.splitSuffixBy p (FL.toList) (S.fromList xs)
2983+-- > splitOnSuffix' p xs = S.toList $ S.splitSuffixBy p (FL.toList) (S.fromList xs)
2980-- >>> splitOnSuffix' (== '.') ""
2985-- >>> splitOnSuffix' (== '.') ""
@@ -3021,7 +3026,7 @@ splitOnSuffix predicate f m =
3021-- @["a","b"]@. In other words, it treats the input like words separated by
3026-- @["a","b"]@. In other words, it treats the input like words separated by
3022-- whitespace elements determined by the predicate.
3027-- whitespace elements determined by the predicate.
3024−-- > wordsBy' p xs = S.toList $ FL.wordsBy p (FL.toList) (S.fromList xs)
3029+-- > wordsBy' p xs = S.toList $ S.wordsBy p (FL.toList) (S.fromList xs)
3026-- >>> wordsBy' (== ',') ""
3031-- >>> wordsBy' (== ',') ""
@@ -3045,7 +3050,7 @@ wordsBy predicate f m =
3045-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
3050-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
3046-- splits.
3051-- splits.
3048−-- > splitBySuffix' p xs = S.toList $ FL.splitBySuffix p (FL.toList) (S.fromList xs)
3053+-- > splitBySuffix' p xs = S.toList $ S.splitBySuffix p (FL.toList) (S.fromList xs)
3050-- >>> splitBySuffix' (== '.') ""
3055-- >>> splitBySuffix' (== '.') ""
@@ -3119,7 +3124,7 @@ splitBySuffix predicate f m =
3119-- For illustration, let's define a function that operates on pure lists:
3124-- For illustration, let's define a function that operates on pure lists:
3122−-- splitOnSeq' pat xs = S.toList $ FL.splitOnSeq (A.fromList pat) (FL.toList) (S.fromList xs)
3127+-- splitOnSeq' pat xs = S.toList $ S.splitOnSeq (A.fromList pat) (FL.toList) (S.fromList xs)
3125-- >>> splitOnSeq' "" "hello"
3130-- >>> splitOnSeq' "" "hello"
@@ -3184,7 +3189,7 @@ splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.to
3184-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
3189-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
3185-- of a predicate for a single element.
3190-- of a predicate for a single element.
3187−-- > splitSuffixOn_ pat xs = S.toList $ FL.splitSuffixOn (A.fromList pat) (FL.toList) (S.fromList xs)
3192+-- > splitSuffixOn_ pat xs = S.toList $ S.splitSuffixOn (A.fromList pat) (FL.toList) (S.fromList xs)
3189-- >>> splitSuffixOn_ "." ""
3194-- >>> splitSuffixOn_ "." ""
@@ -3234,7 +3239,7 @@ wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStream
3235-- | Like 'splitOnSeq' but splits the separator as well, as an infix token.
3240-- | Like 'splitOnSeq' but splits the separator as well, as an infix token.
3237−-- > splitOn'_ pat xs = S.toList $ FL.splitOn' (A.fromList pat) (FL.toList) (S.fromList xs)
3242+-- > splitOn'_ pat xs = S.toList $ S.splitOn' (A.fromList pat) (FL.toList) (S.fromList xs)
3239-- >>> splitOn'_ "" "hello"
3244-- >>> splitOn'_ "" "hello"
3240-- > ["h","","e","","l","","l","","o"]
3245-- > ["h","","e","","l","","l","","o"]