@@ -170,16 +170,18 @@ module Streamly.Prelude
170170-- the previous step. However, it is possible to fold parts of the stream in
171171-- parallel and then combine the results using a monoid.
172172
173+ -- ** Right Folds
173174 , foldrM
174175 , foldrS
175176 , foldrT
176177 , foldr
177178
179+ -- ** Left Folds
178180 , foldl'
179181 , foldl1'
180182 , foldlM'
181183
182− -- * Running Folds
184+ -- ** Composable Left Folds
183185 -- $runningfolds
184186
185187 , runFold
@@ -316,6 +318,7 @@ module Streamly.Prelude
316318 -- > foldl f z xs = last $ scanl f z xs
317319 -- > foldr f z xs = head $ scanr f z xs
318320
321+ -- ** Left scans
319322 , scanl'
320323 , scanlM'
321324 , postscanl'
@@ -325,7 +328,7 @@ module Streamly.Prelude
325328 , scanl1'
326329 , scanl1M'
327330
328− -- ** Running Scans
331+ -- ** Scan Using Fold
329332 , runScan
330333 , runPostscan
331334
@@ -339,6 +342,7 @@ module Streamly.Prelude
339342 -- , lprescanl'
340343 -- , lprescanlM'
341344
345+ -- ** Indexing
342346 , indexed
343347 , indexedR
344348 -- , timestamped
@@ -460,7 +464,7 @@ module Streamly.Prelude
460464 -- , interposeBy
461465 -- , intercalate
462466
463− -- ** Breaking
467+ -- -- ** Breaking
464468
465469 -- By chunks
466470 -- , splitAt -- spanN
@@ -490,14 +494,14 @@ module Streamly.Prelude
490494
491495 -- , groupScan
492496
493− -- *** Chunks
497+ -- -- *** Chunks
494498 , chunksOf
495499 , sessionsOf
496500
497501 -- , lchunksOf
498502 -- , lsessionsOf
499503
500− -- *** Using Element Separators
504+ -- -- *** Using Element Separators
501505 -- On == Dropping the separator
502506 , splitOn
503507 , splitOnSuffix
@@ -1346,19 +1350,20 @@ foldlM' step begin m = S.foldlM' step begin $ toStreamS m
13461350
13471351-- $runningfolds
13481352--
1349−-- We can use the left folds in this module instead of the folds in
1350−-- "Streamly.Prelude". For example the following two ways of folding are
1351−-- equivalent in functionality and performance,
1353+-- "Streamly.Fold" module defines composable left folds which can be combined
1354+-- together in many interesting ways. Those folds can be run using 'runFold'.
1355+-- The following two ways of folding are equivalent in functionality and
1356+-- performance,
13521357--
1353−-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
1358+-- >>> S.runFold FL.sum (S.enumerateFromTo 1 100)
13541359-- 5050
13551360-- >>> S.sum (S.enumerateFromTo 1 100)
13561361-- 5050
13571362--
1358−-- However, left folds are push type folds. That means we push the entire input
1359−-- to a fold before we can get the output. Therefore, the performance is
1363+-- However, left folds cannot terminate early even if it does not need to
1364+-- consume more input to determine the result. Therefore, the performance is
13601365-- 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
13621367-- efficient because they are implemented as right folds that terminate as soon
13631368-- as we get the result. Note that when a full fold is composed with a partial
13641369-- 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
13661371--
13671372-- >>> S.head (1 `S.cons` undefined)
13681373-- Just 1
1369−-- >>> FL.foldl' FL.head (1 `S.cons` undefined)
1374+-- >>> S.runFold FL.head (1 `S.cons` undefined)
13701375-- *** Exception: Prelude.undefined
13711376--
13721377-- However, we can wrap the fold in a scan to convert it into a lazy stream of
13731378-- fold steps. We can then terminate the stream whenever we want. For example,
13741379--
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)
13761381-- [Nothing]
13771382--
13781383-- 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
13821387-- > S.toList
13831388-- $ S.map (fromJust . fst)
13841389-- $ 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)
13861391-- @
13871392-- @
13881393-- [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]
13891394-- @
13901395
1391−-- | Fold a stream using the supplied monadic fold.
1396+-- | Fold a stream using the supplied left fold.
13921397--
1393−-- >>> S.foldlStream FL.sum (S.enumerateFromTo 1 100)
1398+-- >>> S.runFold FL.sum (S.enumerateFromTo 1 100)
13941399-- 5050
13951400--
13961401-- @since 0.7.0
@@ -2181,15 +2186,15 @@ mapMaybeMSerial f m = fromStreamD $ D.mapMaybeM f $ toStreamD m
21812186-- XXX Use a compact region list to temporarily store the list, in both reverse
21822187-- as well as in reverse'.
21832188--
2189+-- /Note:/ 'reverse'' is much faster than this, use that when performance
2190+-- matters.
2191+--
21842192-- |
21852193-- > reverse = S.foldlT (flip S.cons) S.nil
21862194--
21872195-- Returns the elements of the stream in reverse order. The stream must be
21882196-- finite. Note that this necessarily buffers the entire stream in memory.
21892197--
2190−-- /Note:/ 'reverse'' is much faster than this, use that when performance
2191−-- matters.
2192−--
21932198-- /Since 0.7.0 (Monad m constraint)/
21942199--
21952200-- /Since: 0.1.1/
@@ -2567,7 +2572,7 @@ intercalate :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
25672572-- elements of its input are consumed by fold @f1@ and the rest of the stream
25682573-- is consumed by fold @f2@.
25692574--
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
25712576--
25722577-- >>> splitAt_ 6 "Hello World!"
25732578-- > ("Hello ","World!")
@@ -2656,7 +2661,7 @@ groupScan split fold m = undefined
26562661-- | Group the input stream into groups of @n@ elements each and then fold each
26572662-- group using the provided fold function.
26582663--
2659−-- >> S.toList $ FL.chunksOf 2 FL.sum (S.enumerateFromTo 1 10)
2664+-- >> S.toList $ S.chunksOf 2 FL.sum (S.enumerateFromTo 1 10)
26602665-- > [3,7,11,15,19]
26612666--
26622667-- 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) =
27362741-- input as long as the predicate @p@ is 'True'. @f2@ consumes the rest of the
27372742-- input.
27382743--
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
27402745--
27412746-- >>> span_ (< 1) [1,2,3]
27422747-- > ([],[1,2,3])
@@ -2781,7 +2786,7 @@ span p (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
27812786--
27822787-- This is the binary version of 'splitBy'.
27832788--
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
27852790--
27862791-- >>> break_ (< 1) [3,2,1]
27872792-- > ([3,2,1],[])
@@ -2838,7 +2843,7 @@ _spanRollingBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR)
28382843-- group is folded using the fold @f@ and the result of the fold is emitted in
28392844-- the output stream.
28402845--
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]
28422847-- > [[1,3,7],[0,2,5]]
28432848--
28442849-- @since 0.7.0
@@ -2859,7 +2864,7 @@ groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
28592864-- comparison fails a new group is started. Each group is folded using the fold
28602865-- @f@.
28612866--
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]
28632868-- > [[1,2,3],[7,8,9]]
28642869--
28652870-- @since 0.7.0
@@ -2878,7 +2883,7 @@ groupsByRolling cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD
28782883--
28792884-- Groups contiguous spans of equal elements together in individual groups.
28802885--
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]
28822887-- > [[1,1],[2,2]]
28832888--
28842889-- @since 0.7.0
@@ -2895,7 +2900,7 @@ groups = groupsBy (==)
28952900-- stream before the sequence and the second part consisting of the sequence
28962901-- and the rest of the stream.
28972902--
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
28992904--
29002905-- >>> breakOn_ "dear" "Hello dear world!"
29012906-- > ("Hello ","dear world!")
@@ -2931,7 +2936,7 @@ breakOn pat f m = undefined
29312936--
29322937-- Let's use the following definition for illustration:
29332938--
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)
29352940--
29362941-- >>> splitOn' (== '.') ""
29372942-- [""]
@@ -2975,7 +2980,7 @@ splitOn predicate f m =
29752980-- ".--." => "" "--"
29762981-- @
29772982--
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)
29792984--
29802985-- >>> splitOnSuffix' (== '.') ""
29812986-- []
@@ -3021,7 +3026,7 @@ splitOnSuffix predicate f m =
30213026-- @["a","b"]@. In other words, it treats the input like words separated by
30223027-- whitespace elements determined by the predicate.
30233028--
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)
30253030--
30263031-- >>> wordsBy' (== ',') ""
30273032-- > []
@@ -3045,7 +3050,7 @@ wordsBy predicate f m =
30453050-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
30463051-- splits.
30473052--
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)
30493054--
30503055-- >>> splitBySuffix' (== '.') ""
30513056-- []
@@ -3119,7 +3124,7 @@ splitBySuffix predicate f m =
31193124-- For illustration, let's define a function that operates on pure lists:
31203125--
31213126-- @
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)
31233128-- @
31243129--
31253130-- >>> splitOnSeq' "" "hello"
@@ -3184,7 +3189,7 @@ splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.to
31843189-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
31853190-- of a predicate for a single element.
31863191--
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)
31883193--
31893194-- >>> splitSuffixOn_ "." ""
31903195-- [""]
@@ -3234,7 +3239,7 @@ wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStream
32343239--
32353240-- | Like 'splitOnSeq' but splits the separator as well, as an infix token.
32363241--
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)
32383243--
32393244-- >>> splitOn'_ "" "hello"
32403245-- > ["h","","e","","l","","l","","o"]