@@ -7,7 +7,8 @@
7-- Stability : experimental
7-- Stability : experimental
8-- Portability : GHC
8-- Portability : GHC
10−-- See "Streamly.Data.Fold" for an overview.
10+-- See "Streamly.Data.Fold" for an overview and
11+-- "Streamly.Internal.Data.Fold.Types" for design notes.
12-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
13-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
@@ -17,9 +18,10 @@ module Streamly.Internal.Data.Fold
18 , Fold (..)
19 , Fold (..)
20− -- * Creating
21+ -- * Constructors
22 , mkFoldlM
23 , mkFoldlM
24 , mkFoldrM
26 , mkFoldrM
@@ -27,21 +29,21 @@ module Streamly.Internal.Data.Fold
28 , mkFoldM_
30 , mkFoldM_
30− -- * Generators
32+ -- * Folds
34− -- * Accumulators
37+ -- ** Accumulators
35− -- ** Semigroups and Monoids
38+ -- *** Semigroups and Monoids
39 , foldMapM
42 , foldMapM
41− -- ** Reducers
44+ -- *** Reducers
@@ -52,7 +54,7 @@ module Streamly.Internal.Data.Fold
52 , rollingHashFirstN
54 , rollingHashFirstN
53 -- , rollingHashLastN
55 -- , rollingHashLastN
55− -- ** Saturating Reducers
57+ -- *** Saturating Reducers
56 -- | 'product' terminates if it becomes 0. Other folds can theoretically
58 -- | 'product' terminates if it becomes 0. Other folds can theoretically
57 -- saturate on bounded types, and therefore terminate, however, they will
59 -- saturate on bounded types, and therefore terminate, however, they will
58 -- run forever on unbounded types like Integer/Double.
60 -- run forever on unbounded types like Integer/Double.
@@ -63,14 +65,17 @@ module Streamly.Internal.Data.Fold
63 , minimumBy
65 , minimumBy
66− -- ** Collectors
68+ -- *** Collectors
69+ -- | Avoid using these folds in scalable or performance critical
70+ -- applications, they buffer all the input in GC memory which can be
71+ -- detrimental to performance if the input is large.
68 , toListRev
73 , toListRev
69 -- $toListRev
74 -- $toListRev
70 , toStream
75 , toStream
71 , toStreamRev
76 , toStreamRev
73− -- * Terminating Folds
78+ -- ** Terminating Folds
75 -- , lastN
80 -- , lastN
@@ -91,26 +96,21 @@ module Streamly.Internal.Data.Fold
94− -- * Adapting
99+ -- * Combinators
103+ -- ** Transforming the Monad
96 , generally
105 , generally
98− -- * Running Incrementally
107+ -- ** Mapping on output
102− -- * Output Transformations
107− -- * Input Transformations
109− -- ** Mapping
110+ -- ** Mapping on Input
110 , transform
111 , transform
114 --, lsequence
114 --, lsequence
116 , indexed
116 , indexed
@@ -125,63 +125,67 @@ module Streamly.Internal.Data.Fold
125 -- ** Mapping Filters
125 -- ** Mapping Filters
126 , catMaybes
126 , catMaybes
127 , mapMaybe
127 , mapMaybe
130 -- ** Scanning Filters
131 -- ** Scanning Filters
131− , lfindIndices
132+ , findIndices
132− , lelemIndices
133+ , elemIndices
134 -- ** Insertion
135 -- ** Insertion
135 -- | Insertion adds more elements to the stream.
136 -- | Insertion adds more elements to the stream.
137− , linsertBy
138+ , insertBy
138− , lintersperseM
139+ , intersperseM
140 -- ** Reordering
141 -- ** Reordering
141− , lreverse
142+ , reverse
144 -- ** Trimming
145 -- ** Trimming
146 , takeInterval
147 , takeInterval
147 -- By elements
149 -- By elements
149 , takeEndBy
150 , takeEndBy
150 -- , takeEndBySeq
152 -- , takeEndBySeq
153− , ldropWhile
155+ , dropWhile
154− , ldropWhileM
156+ , dropWhileM
157− -- * Splitting
159+ -- ** Serial Append
160 -- , tail
161 -- , tail
161 -- , init
162 -- , init
162 , splitAt -- spanN
163 , splitAt -- spanN
163 -- , splitIn -- sessionN
164 -- , splitIn -- sessionN
165− -- * Distributing
166+ -- ** Parallel Distribution
168 , teeWith
167 , teeWith
169 , teeWithFst
169 , teeWithFst
170 , teeWithMin
170 , teeWithMin
171 , distribute
171 , distribute
172 -- , distributeFst
172 -- , distributeFst
173 -- , distributeMin
173 -- , distributeMin
175− -- * Partitioning
175+ -- ** Parallel Alternative
177 , partitionByM
180 , partitionByM
178 , partitionByFstM
181 , partitionByFstM
179 , partitionByMinM
182 , partitionByMinM
180 , partitionBy
183 , partitionBy
181 , partition
184 , partition
183− -- * Demultiplexing
186+ -- ** Demultiplexing
184−
187+ -- | Direct values in the input stream to different folds using an n-ary
185 , demux -- XXX rename this to demux_
189 , demux -- XXX rename this to demux_
186 , demuxWith
190 , demuxWith
187 , demuxDefault -- XXX rename this to demux
191 , demuxDefault -- XXX rename this to demux
@@ -189,31 +193,47 @@ module Streamly.Internal.Data.Fold
189 -- , demuxWithSel
193 -- , demuxWithSel
190 -- , demuxWithMin
194 -- , demuxWithMin
192− -- * Classifying
196+ -- ** Classifying
193−
197+ -- | In an input stream of key value pairs fold values for different keys
198+ -- in individual output buckets using the given fold.
194 , classify
199 , classify
195 , classifyWith
200 , classifyWith
196 -- , classifyWithSel
201 -- , classifyWithSel
197 -- , classifyWithMin
202 -- , classifyWithMin
199− -- * Unzipping
204+ -- ** Unzipping
206+ -- These two can be expressed using lmap/lmapM and unzip
201 , unzipWith
207 , unzipWith
202 , unzipWithM
208 , unzipWithM
203 , unzipWithFstM
209 , unzipWithFstM
204 , unzipWithMinM
210 , unzipWithMinM
206− -- * Nesting
212+ -- ** Zipping
208 , intervalsOf
218 , intervalsOf
209 , chunksOf
219 , chunksOf
210 , chunksBetween
220 , chunksBetween
214 , concatSequence
223 , concatSequence
215 , concatMap
224 , concatMap
226+ -- * Running Partially
216 , duplicate
229 , duplicate
@@ -228,7 +248,6 @@ import Data.Semigroup (Semigroup((<>)))
229import Streamly.Internal.Data.Either.Strict
249import Streamly.Internal.Data.Either.Strict
230 (Either'(..), fromLeft', fromRight', isLeft', isRight')
250 (Either'(..), fromLeft', fromRight', isLeft', isRight')
231−import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
232import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
251import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
233import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
252import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
234import Streamly.Internal.Data.Stream.Serial (SerialT)
253import Streamly.Internal.Data.Stream.Serial (SerialT)
@@ -270,7 +289,7 @@ hoist f (Fold step initial extract) =
271-- | Adapt a pure fold to any monad
290-- | Adapt a pure fold to any monad
273−-- > generally = hoist (return . runIdentity)
292+-- > generally = Fold.hoist (return . runIdentity)
275-- /Pre-release/
294-- /Pre-release/
276generally :: Monad m => Fold Identity a b -> Fold m a b
295generally :: Monad m => Fold Identity a b -> Fold m a b
@@ -305,7 +324,7 @@ mapM = rmapM
305-- >>> Stream.fold fld (Stream.enumerateFromTo 1 10)
324-- >>> Stream.fold fld (Stream.enumerateFromTo 1 10)
306-- [2,4,6,8,10]
325-- [2,4,6,8,10]
308−-- /Pre-release/
327+-- @since 0.8.0
309{-# INLINE mapMaybe #-}
328{-# INLINE mapMaybe #-}
310mapMaybe :: (Monad m) => (a -> Maybe b) -> Fold m b r -> Fold m a r
329mapMaybe :: (Monad m) => (a -> Maybe b) -> Fold m b r -> Fold m a r
311mapMaybe f = map f . filter isJust . map fromJust
330mapMaybe f = map f . filter isJust . map fromJust
@@ -318,7 +337,7 @@ mapMaybe f = map f . filter isJust . map fromJust
319-- | Apply a transformation on a 'Fold' using a 'Pipe'.
338-- | Apply a transformation on a 'Fold' using a 'Pipe'.
321−-- @since 0.7.0
340+-- /Pre-release/
322{-# INLINE transform #-}
341{-# INLINE transform #-}
323transform :: Monad m => Pipe m a b -> Fold m b c -> Fold m a c
342transform :: Monad m => Pipe m a b -> Fold m b c -> Fold m a c
324transform (Pipe pstep1 pstep2 pinitial) (Fold fstep finitial fextract) =
343transform (Pipe pstep1 pstep2 pinitial) (Fold fstep finitial fextract) =
@@ -355,23 +374,6 @@ transform (Pipe pstep1 pstep2 pinitial) (Fold fstep finitial fextract) =
356 extract (Tuple' _ fs) = fextract fs
375 extract (Tuple' _ fs) = fextract fs
358−------------------------------------------------------------------------------
360−------------------------------------------------------------------------------
362−-- | @_Fold1 step@ returns a new 'Fold' using just a step function that has the
363−-- same type for the accumulator and the element. The result type is the
364−-- accumulator type wrapped in 'Maybe'. The initial accumulator is retrieved
365−-- from the 'Foldable', the result is 'None' for empty containers.
366−{-# INLINABLE _Fold1 #-}
367−_Fold1 :: Monad m => (a -> a -> a) -> Fold m a (Maybe a)
368−_Fold1 step = fmap toMaybe $ mkFoldl step_ Nothing'
372− step_ Nothing' a = Just' a
373− step_ (Just' x) a = Just' $ step x a
375------------------------------------------------------------------------------
377------------------------------------------------------------------------------
376-- Left folds
378-- Left folds
377------------------------------------------------------------------------------
379------------------------------------------------------------------------------
@@ -382,11 +384,13 @@ _Fold1 step = fmap toMaybe $ mkFoldl step_ Nothing'
384-- > drainBy f = lmapM f drain
386-- > drainBy f = lmapM f drain
385−-- > drainBy = FL.foldMapM (void . f)
387+-- > drainBy = Fold.foldMapM (void . f)
387-- Drain all input after passing it through a monadic function. This is the
389-- Drain all input after passing it through a monadic function. This is the
388-- dual of mapM_ on stream producers.
390-- dual of mapM_ on stream producers.
392+-- See also: "Streamly.Prelude.mapM_"
390-- @since 0.7.0
394-- @since 0.7.0
391{-# INLINABLE drainBy #-}
395{-# INLINABLE drainBy #-}
392drainBy :: Monad m => (a -> m b) -> Fold m a ()
396drainBy :: Monad m => (a -> m b) -> Fold m a ()
@@ -401,12 +405,12 @@ drainBy2 f = Fold2 (const (void . f)) (\_ -> return ()) return
402-- | Extract the last element of the input stream, if any.
406-- | Extract the last element of the input stream, if any.
404−-- > last = fmap getLast $ FL.foldMap (Last . Just)
408+-- > last = fmap getLast $ Fold.foldMap (Last . Just)
406-- @since 0.7.0
410-- @since 0.7.0
407{-# INLINABLE last #-}
411{-# INLINABLE last #-}
408last :: Monad m => Fold m a (Maybe a)
412last :: Monad m => Fold m a (Maybe a)
409−last = _Fold1 (\_ x -> x)
413+last = mkFoldl1 (\_ x -> x)
411------------------------------------------------------------------------------
415------------------------------------------------------------------------------
412-- To Summary
416-- To Summary
@@ -416,14 +420,14 @@ last = _Fold1 (\_ x -> x)
417-- > genericLength = fmap getSum $ foldMap (Sum . const 1)
421-- > genericLength = fmap getSum $ foldMap (Sum . const 1)
419−-- @since 0.7.0
423+-- /Pre-release/
420{-# INLINE genericLength #-}
424{-# INLINE genericLength #-}
421genericLength :: (Monad m, Num b) => Fold m a b
425genericLength :: (Monad m, Num b) => Fold m a b
422genericLength = mkFoldl (\n _ -> n + 1) 0
426genericLength = mkFoldl (\n _ -> n + 1) 0
424-- | Determine the length of the input stream.
428-- | Determine the length of the input stream.
426−-- > length = fmap getSum $ foldMap (Sum . const 1)
430+-- > length = fmap getSum $ Fold.foldMap (Sum . const 1)
428-- @since 0.7.0
432-- @since 0.7.0
429{-# INLINE length #-}
433{-# INLINE length #-}
@@ -434,7 +438,7 @@ length = genericLength
434-- identity (@0@) when the stream is empty. Note that this is not numerically
438-- identity (@0@) when the stream is empty. Note that this is not numerically
435-- stable for floating point numbers.
439-- stable for floating point numbers.
437−-- > sum = fmap getSum $ FL.foldMap Sum
441+-- > sum = fmap getSum $ Fold.foldMap Sum
439-- @since 0.7.0
443-- @since 0.7.0
440{-# INLINE sum #-}
444{-# INLINE sum #-}
@@ -445,7 +449,7 @@ sum = mkFoldl (+) 0
445-- multiplicative identity (@1@) when the stream is empty. The fold terminates
449-- multiplicative identity (@1@) when the stream is empty. The fold terminates
446-- when it encounters (@0@) in its input.
450-- when it encounters (@0@) in its input.
448−-- > product = fmap getProduct $ FL.foldMap Product
452+-- Compare with @Fold.foldMap Product@.
450-- @since 0.7.0
454-- @since 0.7.0
451-- /Since 0.8.0 (Added 'Eq' constraint)/
455-- /Since 0.8.0 (Added 'Eq' constraint)/
@@ -470,7 +474,7 @@ product = mkFold_ step (Partial 1)
470-- @since 0.7.0
474-- @since 0.7.0
471{-# INLINE maximumBy #-}
475{-# INLINE maximumBy #-}
472maximumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
476maximumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
473−maximumBy cmp = _Fold1 max'
477+maximumBy cmp = mkFoldl1 max'
@@ -481,24 +485,24 @@ maximumBy cmp = _Fold1 max'
484−-- maximum = 'maximumBy' compare
488+-- maximum = Fold.maximumBy compare
487-- Determine the maximum element in a stream.
491-- Determine the maximum element in a stream.
489−-- Compare with @FL.foldMap Max@.
493+-- Compare with @Fold.foldMap Max@.
491-- @since 0.7.0
495-- @since 0.7.0
492{-# INLINE maximum #-}
496{-# INLINE maximum #-}
493maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
497maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
494−maximum = _Fold1 max
498+maximum = mkFoldl1 max
496-- | Computes the minimum element with respect to the given comparison function
500-- | Computes the minimum element with respect to the given comparison function
498-- @since 0.7.0
502-- @since 0.7.0
499{-# INLINE minimumBy #-}
503{-# INLINE minimumBy #-}
500minimumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
504minimumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
501−minimumBy cmp = _Fold1 min'
505+minimumBy cmp = mkFoldl1 min'
@@ -514,12 +518,12 @@ minimumBy cmp = _Fold1 min'
514-- minimum = 'minimumBy' compare
518-- minimum = 'minimumBy' compare
517−-- Compare with @FL.foldMap Min@.
521+-- Compare with @Fold.foldMap Min@.
519-- @since 0.7.0
523-- @since 0.7.0
520{-# INLINE minimum #-}
524{-# INLINE minimum #-}
521minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
525minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
522−minimum = _Fold1 min
526+minimum = mkFoldl1 min
524------------------------------------------------------------------------------
528------------------------------------------------------------------------------
525-- To Summary (Statistical)
529-- To Summary (Statistical)
@@ -603,7 +607,7 @@ defaultSalt = -2578643520546668380
604-- | Compute an 'Int' sized polynomial rolling hash of a stream.
608-- | Compute an 'Int' sized polynomial rolling hash of a stream.
606−-- > rollingHash = rollingHashWithSalt defaultSalt
610+-- > rollingHash = Fold.rollingHashWithSalt defaultSalt
608-- /Pre-release/
612-- /Pre-release/
609{-# INLINABLE rollingHash #-}
613{-# INLINABLE rollingHash #-}
@@ -613,7 +617,7 @@ rollingHash = rollingHashWithSalt defaultSalt
613-- | Compute an 'Int' sized polynomial rolling hash of the first n elements of
617-- | Compute an 'Int' sized polynomial rolling hash of the first n elements of
614-- a stream.
618-- a stream.
616−-- > rollingHashFirstN = take n rollingHash
620+-- > rollingHashFirstN = Fold.take n Fold.rollingHash
618-- /Pre-release/
622-- /Pre-release/
619{-# INLINABLE rollingHashFirstN #-}
623{-# INLINABLE rollingHashFirstN #-}
@@ -626,10 +630,14 @@ rollingHashFirstN n = take n rollingHash
627-- | Append the elements of an input stream to a provided starting value.
631-- | Append the elements of an input stream to a provided starting value.
629−-- > S.fold (FL.sconcat 10) (S.map Sum $ S.enumerateFromTo 1 10)
633+-- >>> Stream.fold (Fold.sconcat 10) (Stream.map Data.Monoid.Sum $ Stream.enumerateFromTo 1 10)
631−-- /Pre-release/
636+-- @
637+-- sconcat = Fold.mkFoldl (<>)
633{-# INLINE sconcat #-}
641{-# INLINE sconcat #-}
634sconcat :: (Monad m, Semigroup a) => a -> Fold m a a
642sconcat :: (Monad m, Semigroup a) => a -> Fold m a a
635sconcat = mkFoldl (<>)
643sconcat = mkFoldl (<>)
@@ -637,7 +645,10 @@ sconcat = mkFoldl (<>)
637-- | Fold an input stream consisting of monoidal elements using 'mappend'
645-- | Fold an input stream consisting of monoidal elements using 'mappend'
638-- and 'mempty'.
646-- and 'mempty'.
640−-- > S.fold FL.mconcat (S.map Sum $ S.enumerateFromTo 1 10)
648+-- >>> Stream.fold Fold.mconcat (Stream.map Data.Monoid.Sum $ Stream.enumerateFromTo 1 10)
651+-- > mconcat = Fold.sconcat mempty
642-- @since 0.7.0
653-- @since 0.7.0
643{-# INLINE mconcat #-}
654{-# INLINE mconcat #-}
@@ -650,12 +661,13 @@ mconcat ::
650mconcat = sconcat mempty
661mconcat = sconcat mempty
653−-- > foldMap f = map f mconcat
664+-- > foldMap f = Fold.lmap f Fold.mconcat
655-- Make a fold from a pure function that folds the output of the function
666-- Make a fold from a pure function that folds the output of the function
656-- using 'mappend' and 'mempty'.
667-- using 'mappend' and 'mempty'.
658−-- > S.fold (FL.foldMap Sum) $ S.enumerateFromTo 1 10
669+-- >>> Stream.fold (Fold.foldMap Data.Monoid.Sum) $ Stream.enumerateFromTo 1 10
660-- @since 0.7.0
672-- @since 0.7.0
661{-# INLINABLE foldMap #-}
673{-# INLINABLE foldMap #-}
@@ -664,15 +676,16 @@ foldMap :: (Monad m, Monoid b
664 , Semigroup b
676 , Semigroup b
666 ) => (a -> b) -> Fold m a b
678 ) => (a -> b) -> Fold m a b
667−foldMap f = map f mconcat
679+foldMap f = lmap f mconcat
670−-- > foldMapM f = lmapM f mconcat
682+-- > foldMapM f = Fold.lmapM f Fold.mconcat
672-- Make a fold from a monadic function that folds the output of the function
684-- Make a fold from a monadic function that folds the output of the function
673-- using 'mappend' and 'mempty'.
685-- using 'mappend' and 'mempty'.
675−-- > S.fold (FL.foldMapM (return . Sum)) $ S.enumerateFromTo 1 10
687+-- >>> Stream.fold (Fold.foldMapM (return . Data.Monoid.Sum)) $ Stream.enumerateFromTo 1 10
677-- @since 0.7.0
690-- @since 0.7.0
678{-# INLINABLE foldMapM #-}
691{-# INLINABLE foldMapM #-}
@@ -695,10 +708,12 @@ foldMapM act = mkFoldlM step (pure mempty)
696-- | Buffers the input stream to a list in the reverse order of the input.
709-- | Buffers the input stream to a list in the reverse order of the input.
711+-- > toListRev = Fold.mkFoldl (flip (:)) []
698-- /Warning!/ working on large lists accumulated as buffers in memory could be
713-- /Warning!/ working on large lists accumulated as buffers in memory could be
699-- very inefficient, consider using "Streamly.Array" instead.
714-- very inefficient, consider using "Streamly.Array" instead.
701−-- @since 0.7.0
716+-- @since 0.8.0
703-- xn : ... : x2 : x1 : []
718-- xn : ... : x2 : x1 : []
704{-# INLINABLE toListRev #-}
719{-# INLINABLE toListRev #-}
@@ -711,6 +726,10 @@ toListRev = mkFoldl (flip (:)) []
712-- | A fold that drains the first n elements of its input, running the effects
727-- | A fold that drains the first n elements of its input, running the effects
713-- and discarding the results.
728-- and discarding the results.
730+-- > drainN n = Fold.take n Fold.drain
714{-# INLINABLE drainN #-}
733{-# INLINABLE drainN #-}
715drainN :: Monad m => Int -> Fold m a ()
734drainN :: Monad m => Int -> Fold m a ()
716drainN n = take n drain
735drainN n = take n drain
@@ -735,6 +754,8 @@ genericIndex i = mkFold step (Partial 0) (const Nothing)
736-- | Lookup the element at the given index.
755-- | Lookup the element at the given index.
757+-- See also: "Streamly.Prelude.!!"
738-- @since 0.7.0
759-- @since 0.7.0
739{-# INLINABLE index #-}
760{-# INLINABLE index #-}
740index :: Monad m => Int -> Fold m a (Maybe a)
761index :: Monad m => Int -> Fold m a (Maybe a)
@@ -742,8 +763,6 @@ index = genericIndex
743-- | Extract the first element of the stream, if any.
764-- | Extract the first element of the stream, if any.
745−-- > head = fmap getFirst $ FL.foldMap (First . Just)
747-- @since 0.7.0
766-- @since 0.7.0
748{-# INLINABLE head #-}
767{-# INLINABLE head #-}
749head :: Monad m => Fold m a (Maybe a)
768head :: Monad m => Fold m a (Maybe a)
@@ -751,11 +770,6 @@ head = mkFold_ (const (Done . Just)) (Partial Nothing)
752-- | Returns the first element that satisfies the given predicate.
771-- | Returns the first element that satisfies the given predicate.
755−-- find p = fmap getFirst $
756−-- FL.foldMap (\x -> First (if p x then Just x else Nothing))
759-- @since 0.7.0
773-- @since 0.7.0
760{-# INLINABLE find #-}
774{-# INLINABLE find #-}
761find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
775find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
@@ -771,7 +785,7 @@ find predicate = mkFold step (Partial ()) (const Nothing)
771-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
785-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
772-- first pair where the key equals the given value @a@.
786-- first pair where the key equals the given value @a@.
774−-- > lookup = snd <$> find ((==) . fst)
788+-- > lookup = snd <$> Fold.find ((==) . fst)
776-- @since 0.7.0
790-- @since 0.7.0
777{-# INLINABLE lookup #-}
791{-# INLINABLE lookup #-}
@@ -801,7 +815,7 @@ findIndex predicate = mkFold step (Partial 0) (const Nothing)
802-- | Returns the first index where a given value is found in the stream.
816-- | Returns the first index where a given value is found in the stream.
804−-- > elemIndex a = findIndex (== a)
818+-- > elemIndex a = Fold.findIndex (== a)
806-- @since 0.7.0
820-- @since 0.7.0
807{-# INLINABLE elemIndex #-}
821{-# INLINABLE elemIndex #-}
@@ -814,22 +828,20 @@ elemIndex a = findIndex (a ==)
815-- | Return 'True' if the input stream is empty.
829-- | Return 'True' if the input stream is empty.
817−-- > null = fmap isJust head
831+-- > null = fmap isJust Fold.head
819-- @since 0.7.0
833-- @since 0.7.0
820{-# INLINABLE null #-}
834{-# INLINABLE null #-}
821null :: Monad m => Fold m a Bool
835null :: Monad m => Fold m a Bool
822null = mkFold (\() _ -> Done False) (Partial ()) (const True)
836null = mkFold (\() _ -> Done False) (Partial ()) (const True)
825−-- > any p = map p or
826−-- > any p = fmap getAny . FL.foldMap (Any . p)
828-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
838-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
830-- >>> Stream.fold (Fold.any (== 0)) $ Stream.fromList [1,0,1]
840-- >>> Stream.fold (Fold.any (== 0)) $ Stream.fromList [1,0,1]
843+-- > any p = Fold.lmap p Fold.or
833-- @since 0.7.0
845-- @since 0.7.0
834{-# INLINE any #-}
846{-# INLINE any #-}
835any :: Monad m => (a -> Bool) -> Fold m a Bool
847any :: Monad m => (a -> Bool) -> Fold m a Bool
@@ -846,22 +858,20 @@ any predicate = mkFold_ step initial
847-- | Return 'True' if the given element is present in the stream.
859-- | Return 'True' if the given element is present in the stream.
849−-- > elem a = any (== a)
861+-- > elem a = Fold.any (== a)
851-- @since 0.7.0
863-- @since 0.7.0
852{-# INLINABLE elem #-}
864{-# INLINABLE elem #-}
853elem :: (Eq a, Monad m) => a -> Fold m a Bool
865elem :: (Eq a, Monad m) => a -> Fold m a Bool
854elem a = any (a ==)
866elem a = any (a ==)
857−-- > all p = map p and
858−-- > all p = fmap getAll . FL.foldMap (All . p)
860-- | Returns 'True' if all elements of a stream satisfy a predicate.
868-- | Returns 'True' if all elements of a stream satisfy a predicate.
862-- >>> Stream.fold (Fold.all (== 0)) $ Stream.fromList [1,0,1]
870-- >>> Stream.fold (Fold.all (== 0)) $ Stream.fromList [1,0,1]
873+-- > all p = Fold.lmap p Fold.and
865-- @since 0.7.0
875-- @since 0.7.0
866{-# INLINABLE all #-}
876{-# INLINABLE all #-}
867all :: Monad m => (a -> Bool) -> Fold m a Bool
877all :: Monad m => (a -> Bool) -> Fold m a Bool
@@ -878,7 +888,7 @@ all predicate = mkFold_ step initial
879-- | Returns 'True' if the given element is not present in the stream.
889-- | Returns 'True' if the given element is not present in the stream.
881−-- > notElem a = all (/= a)
891+-- > notElem a = Fold.all (/= a)
883-- @since 0.7.0
893-- @since 0.7.0
884{-# INLINABLE notElem #-}
894{-# INLINABLE notElem #-}
@@ -887,8 +897,7 @@ notElem a = all (a /=)
888-- | Returns 'True' if all elements are 'True', 'False' otherwise
898-- | Returns 'True' if all elements are 'True', 'False' otherwise
890−-- > and = all (== True)
900+-- > and = Fold.all (== True)
891−-- > and = fmap getAll . FL.foldMap All
893-- @since 0.7.0
902-- @since 0.7.0
894{-# INLINE and #-}
903{-# INLINE and #-}
@@ -897,8 +906,7 @@ and = all (== True)
898-- | Returns 'True' if any element is 'True', 'False' otherwise
907-- | Returns 'True' if any element is 'True', 'False' otherwise
900−-- > or = any (== True)
909+-- > or = Fold.any (== True)
901−-- > or = fmap getAny . FL.foldMap Any
903-- @since 0.7.0
911-- @since 0.7.0
904{-# INLINE or #-}
912{-# INLINE or #-}
@@ -917,8 +925,6 @@ or = any (== True)
917-- Binary APIs
925-- Binary APIs
918------------------------------------------------------------------------------
926------------------------------------------------------------------------------
920−-- XXX These would just be applicative compositions of terminating folds.
922-- | @splitAt n f1 f2@ composes folds @f1@ and @f2@ such that first @n@
928-- | @splitAt n f1 f2@ composes folds @f1@ and @f2@ such that first @n@
923-- elements of its input are consumed by fold @f1@ and the rest of the stream
929-- elements of its input are consumed by fold @f1@ and the rest of the stream
924-- is consumed by fold @f2@.
930-- is consumed by fold @f2@.
@@ -943,7 +949,7 @@ or = any (== True)
943-- >>> splitAt_ 4 [1,2,3]
949-- >>> splitAt_ 4 [1,2,3]
944-- ([1,2,3],[])
950-- ([1,2,3],[])
946−-- > splitAt n f1 f2 = serialWith (,) (take n f1) f2
952+-- > splitAt n f1 f2 = Fold.serialWith (,) (Fold.take n f1) f2
948-- /Internal/
954-- /Internal/
@@ -967,53 +973,22 @@ splitAt n fld = serialWith (,) (take n fld)
967-- Note: Keep this consistent with S.splitOn. In fact we should eliminate
973-- Note: Keep this consistent with S.splitOn. In fact we should eliminate
968-- S.splitOn in favor of the fold.
974-- S.splitOn in favor of the fold.
970−-- | Consume the input until it encounters an infixed separator element (i.e.
976+-- XXX Use Fold.many instead once it is fixed.
971−-- when the supplied predicate succeeds), dropping the separator.
973−-- Repeated applications of 'takeEndBy_' splits the stream on separator
974−-- elements determined by the supplied predicate, separator is considered as
975−-- infixed between two segments, if one side of the separator is missing then
976−-- it is parsed as an empty stream. The supplied 'Fold' is applied on the
977−-- split segments. With '-' representing non-separator elements and '.' as
978−-- separator, repeated 'takeEndBy_' splits the stream as follows:
981−-- "--.--" => "--" "--"
986−-- Repeated applications of @Fold.takeEndBy_ (== x)@ on the input stream gives us
987−-- an inverse of @Stream.intercalate (Stream.yield x)@
989−-- > Stream.splitOn pred f = Stream.foldMany (Fold.takeEndBy_ pred f)
991−-- Let's use the following definition for illustration:
993−-- >>> splitOn p = Stream.foldMany (Fold.takeEndBy_ pred Fold.toList)
994−-- >>> splitOn' p = Stream.toList . splitOn p . Stream.fromList
996−-- >>> splitOn' (== '.') ""
999−-- >>> splitOn' (== '.') "."
1002−-- >>> splitOn' (== '.') ".a"
978+-- | Like 'takeEndBy' but drops the element on which the predicate succeeds.
1005−-- >>> splitOn' (== '.') "a."
980+-- >>> Stream.fold (Fold.takeEndBy_ (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
1006−-- ["a",""]
981+-- "hello"
1008−-- >>> splitOn' (== '.') "a.b"
983+-- >>> Stream.toList $ Stream.foldMany (Fold.takeEndBy_ (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
1009−-- ["a","b"]
984+-- ["hello","there"]
1011−-- >>> splitOn' (== '.') "a..b"
986+-- > Stream.splitOnSuffix p f = Stream.foldMany (Fold.takeEndBy_ p f)
1014−-- Stops - when the predicate succeeds.
988+-- See 'Streamly.Prelude.splitOnSuffix' for more details on splitting a
989+-- stream using 'takeEndBy_'.
1016−-- /Pre-release/
991+-- @since 0.8.0
1017{-# INLINE takeEndBy_ #-}
992{-# INLINE takeEndBy_ #-}
1018takeEndBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
993takeEndBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1019takeEndBy_ predicate (Fold fstep finitial fextract) =
994takeEndBy_ predicate (Fold fstep finitial fextract) =
@@ -1026,16 +1001,21 @@ takeEndBy_ predicate (Fold fstep finitial fextract) =
1026 then fstep s a
1001 then fstep s a
1027 else Done <$> fextract s
1002 else Done <$> fextract s
1029−-- | Collect stream elements until an element succeeds the predicate. Also take
1004+-- | Take the input, stop when the predicate succeeds taking the succeeding
1030−-- the element on which the predicate succeeded. The succeeding element is
1005+-- element as well.
1031−-- treated as a suffix separator which is kept in the output segement.
1033−-- * Stops - when the predicate succeeds.
1007+-- >>> Stream.fold (Fold.takeEndBy (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
1035−-- > Stream.splitWithSuffix pred f = Stream.foldMany (Fold.takeEndBy pred f)
1010+-- >>> Stream.toList $ Stream.foldMany (Fold.takeEndBy (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
1011+-- ["hello\n","there\n"]
1037−-- /Pre-release/
1013+-- > Stream.splitWithSuffix p f = Stream.foldMany (Fold.takeEndBy p f)
1015+-- See 'Streamly.Prelude.splitWithSuffix' for more details on splitting a
1016+-- stream using 'takeEndBy'.
1039{-# INLINE takeEndBy #-}
1019{-# INLINE takeEndBy #-}
1040takeEndBy :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1020takeEndBy :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1041takeEndBy predicate (Fold fstep finitial fextract) =
1021takeEndBy predicate (Fold fstep finitial fextract) =
@@ -1086,6 +1066,8 @@ breakOn pat f m = undefined
1086-- >>> Stream.fold (Fold.tee Fold.sum Fold.length) (Stream.enumerateFromTo 1.0 100.0)
1066-- >>> Stream.fold (Fold.tee Fold.sum Fold.length) (Stream.enumerateFromTo 1.0 100.0)
1087-- (5050.0,100)
1067-- (5050.0,100)
1069+-- > tee = teeWith (,)
1089-- @since 0.7.0
1071-- @since 0.7.0
1090{-# INLINE tee #-}
1072{-# INLINE tee #-}
1091tee :: Monad m => Fold m a b -> Fold m a c -> Fold m a (b,c)
1073tee :: Monad m => Fold m a b -> Fold m a c -> Fold m a (b,c)
@@ -1110,6 +1092,8 @@ tee = teeWith (,)
1110-- >>> Stream.fold (Fold.distribute [Fold.sum, Fold.length]) (Stream.enumerateFromTo 1 5)
1092-- >>> Stream.fold (Fold.distribute [Fold.sum, Fold.length]) (Stream.enumerateFromTo 1 5)
1111-- [15,5]
1093-- [15,5]
1095+-- > distribute = Prelude.foldr (Fold.teeWith (:)) (Fold.yield [])
1113-- This is the consumer side dual of the producer side 'sequence' operation.
1097-- This is the consumer side dual of the producer side 'sequence' operation.
1115-- Stops when all the folds stop.
1099-- Stops when all the folds stop.
@@ -1171,7 +1155,7 @@ distribute = foldr (teeWith (:)) (yield [])
1172-- /See also: 'partitionByFstM' and 'partitionByMinM'./
1156-- /See also: 'partitionByFstM' and 'partitionByMinM'./
1174−-- @since 0.7.0
1158+-- /Pre-release/
1175{-# INLINE partitionByM #-}
1159{-# INLINE partitionByM #-}
1176partitionByM :: Monad m
1160partitionByM :: Monad m
1177 => (a -> m (Either b c)) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1161 => (a -> m (Either b c)) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
@@ -1270,7 +1254,7 @@ partitionByMinM = undefined
1271-- ("Even 50","Odd 50")
1255-- ("Even 50","Odd 50")
1273−-- @since 0.7.0
1257+-- /Pre-release/
1274{-# INLINE partitionBy #-}
1258{-# INLINE partitionBy #-}
1275partitionBy :: Monad m
1259partitionBy :: Monad m
1276 => (a -> Either b c) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1260 => (a -> Either b c) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
@@ -1346,7 +1330,9 @@ demuxWith f kv = fmap fst $ demuxDefaultWith f kv drain
1347-- fromList [("PRODUCT",8),("SUM",4)]
1331-- fromList [("PRODUCT",8),("SUM",4)]
1349−-- @since 0.7.0
1333+-- > demux = demuxWith id
1350{-# INLINE demux #-}
1336{-# INLINE demux #-}
1351demux :: (Monad m, Ord k)
1337demux :: (Monad m, Ord k)
1352 => Map k (Fold m a b) -> Fold m (k, a) (Map k b)
1338 => Map k (Fold m a b) -> Fold m (k, a) (Map k b)
@@ -1476,6 +1462,10 @@ demuxDefaultWith f kv (Fold dstep dinitial dextract) =
1476 b <- dextract dacc
1462 b <- dextract dacc
1477 return (doneMap, b)
1463 return (doneMap, b)
1466+-- > demuxDefault = demuxDefaultWith id
1479{-# INLINE demuxDefault #-}
1469{-# INLINE demuxDefault #-}
1480demuxDefault :: (Monad m, Ord k)
1470demuxDefault :: (Monad m, Ord k)
1481 => Map k (Fold m a b) -> Fold m (k, a) b -> Fold m (k, a) (Map k b, b)
1471 => Map k (Fold m a b) -> Fold m (k, a) b -> Fold m (k, a) (Map k b, b)
@@ -1555,12 +1545,11 @@ classifyWith f (Fold step1 initial1 extract1) =
1556-- fromList [("ONE",[1.0,1.1]),("TWO",[2.0,2.2])]
1546-- fromList [("ONE",[1.0,1.1]),("TWO",[2.0,2.2])]
1560-- Same as:
1548-- Same as:
1562−-- > classify fld = classifyWith fst (map snd fld)
1550+-- > classify fld = Fold.classifyWith fst (map snd fld)
1564{-# INLINE classify #-}
1553{-# INLINE classify #-}
1565classify :: (Monad m, Ord k) => Fold m a b -> Fold m (k, a) (Map k b)
1554classify :: (Monad m, Ord k) => Fold m a b -> Fold m (k, a) (Map k b)
1566classify fld = classifyWith fst (map snd fld)
1555classify fld = classifyWith fst (map snd fld)
@@ -1571,9 +1560,9 @@ classify fld = classifyWith fst (map snd fld)
1572-- | Like 'unzipWith' but with a monadic splitter function.
1561-- | Like 'unzipWith' but with a monadic splitter function.
1574−-- -- @unzipWithM k f1 f2 = lmapM k (unzip f1 f2)@
1563+-- @unzipWithM k f1 f2 = lmapM k (unzip f1 f2)@
1576−-- @since 0.7.0
1565+-- /Pre-release/
1577{-# INLINE unzipWithM #-}
1566{-# INLINE unzipWithM #-}
1578unzipWithM :: Monad m
1567unzipWithM :: Monad m
1579 => (a -> m (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
1568 => (a -> m (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
@@ -1653,11 +1642,11 @@ unzipWithMinM = undefined
1653-- | Split elements in the input stream into two parts using a pure splitter
1642-- | Split elements in the input stream into two parts using a pure splitter
1654-- function, direct each part to a different fold and zip the results.
1643-- function, direct each part to a different fold and zip the results.
1656−-- @unzipWith f fld1 fld2 = map f (unzip fld1 fld2)@
1645+-- @unzipWith f fld1 fld2 = Fold.lmap f (Fold.unzip fld1 fld2)@
1658-- This fold terminates when both the input folds terminate.
1647-- This fold terminates when both the input folds terminate.
1660−-- @since 0.7.0
1649+-- /Pre-release/
1661{-# INLINE unzipWith #-}
1650{-# INLINE unzipWith #-}
1662unzipWith :: Monad m
1651unzipWith :: Monad m
1663 => (a -> (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
1652 => (a -> (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
@@ -1674,6 +1663,8 @@ unzipWith f = unzipWithM (return . f)
1666+-- > unzip = Fold.unzipWith id
1677-- This is the consumer side dual of the producer side 'zip' operation.
1668-- This is the consumer side dual of the producer side 'zip' operation.
1679-- @since 0.7.0
1670-- @since 0.7.0
@@ -1773,6 +1764,8 @@ chunksBetween _low _high _f1 _f2 = undefined
1773-- /Warning!/ working on large streams accumulated as buffers in memory could
1764-- /Warning!/ working on large streams accumulated as buffers in memory could
1774-- be very inefficient, consider using "Streamly.Data.Array" instead.
1765-- be very inefficient, consider using "Streamly.Data.Array" instead.
1767+-- > toStream = mkFoldr K.cons K.nil
1776-- /Pre-release/
1769-- /Pre-release/
1777{-# INLINE toStream #-}
1770{-# INLINE toStream #-}
1778toStream :: Monad m => Fold m a (SerialT Identity a)
1771toStream :: Monad m => Fold m a (SerialT Identity a)
@@ -1784,6 +1777,8 @@ toStream = mkFoldr K.cons K.nil
1784-- | Buffers the input stream to a pure stream in the reverse order of the
1777-- | Buffers the input stream to a pure stream in the reverse order of the
1785-- input.
1778-- input.
1780+-- > toStreamRev = mkFoldl (flip K.cons) K.nil
1787-- /Warning!/ working on large streams accumulated as buffers in memory could
1782-- /Warning!/ working on large streams accumulated as buffers in memory could
1788-- be very inefficient, consider using "Streamly.Data.Array" instead.
1783-- be very inefficient, consider using "Streamly.Data.Array" instead.