on 2c48600 help sign in
1966 lines 58 kB history raw
1-- |
2-- Module : Streamly.Internal.Data.Fold
3-- Copyright : (c) 2019 Composewell Technologies
4-- (c) 2013 Gabriel Gonzalez
5-- License : BSD3
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
8-- Portability : GHC
9--
10-- See "Streamly.Data.Fold" for an overview and
11-- "Streamly.Internal.Data.Fold.Types" for design notes.
12--
13-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
15module Streamly.Internal.Data.Fold
16 (
17 -- * Fold Type
18 Step (..)
19 , Fold (..)
21 -- * Constructors
22 , foldl'
23 , foldlM'
24 , foldl1'
25 , foldr
26 , foldrM
27 , mkFold
28 , mkFold_
29 , mkFoldM
30 , mkFoldM_
32 -- * Folds
33 -- ** Identity
34 , fromPure
35 , fromEffect
37 -- ** Accumulators
38 -- *** Semigroups and Monoids
39 , sconcat
40 , mconcat
41 , foldMap
42 , foldMapM
44 -- *** Reducers
45 , drain
46 , drainBy
47 , last
48 , length
49 , mean
50 , variance
51 , stdDev
52 , rollingHash
53 , rollingHashWithSalt
54 , rollingHashFirstN
55 -- , rollingHashLastN
57 -- *** Saturating Reducers
58 -- | 'product' terminates if it becomes 0. Other folds can theoretically
59 -- saturate on bounded types, and therefore terminate, however, they will
60 -- run forever on unbounded types like Integer/Double.
61 , sum
62 , product
63 , maximumBy
64 , maximum
65 , minimumBy
66 , minimum
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.
72 , toList
73 , toListRev
74 -- $toListRev
75 , toStream
76 , toStreamRev
78 -- ** Terminating Folds
79 , drainN
80 -- , lastN
81 -- , (!!)
82 , genericIndex
83 , index
84 , head
85 -- , findM
86 , find
87 , lookup
88 , findIndex
89 , elemIndex
90 , null
91 , elem
92 , notElem
93 , all
94 , any
95 , and
96 , or
97 -- , the
99 -- * Combinators
100 -- ** Utilities
101 , with
103 -- ** Transforming the Monad
104 , hoist
105 , generally
107 -- ** Mapping on output
108 , rmapM
110 -- ** Mapping on Input
111 , transform
112 , lmap
113 --, lsequence
114 , lmapM
115 , indexed
117 -- ** Filtering
118 , filter
119 , filterM
120 , sampleFromthen
121 -- , ldeleteBy
122 -- , luniq
124 -- ** Mapping Filters
125 , catMaybes
126 , mapMaybe
127 -- , mapMaybeM
129 {-
130 -- ** Scanning Filters
131 , findIndices
132 , elemIndices
134 -- ** Insertion
135 -- | Insertion adds more elements to the stream.
137 , insertBy
138 , intersperseM
140 -- ** Reordering
141 , reverse
142 -}
144 -- ** Trimming
145 , take
146 , takeInterval
148 -- By elements
149 , takeEndBy
150 , takeEndBy_
151 -- , takeEndBySeq
152 {-
153 , drop
154 , dropWhile
155 , dropWhileM
156 -}
158 -- ** Serial Append
159 , serialWith
160 , serial_
161 -- , tail
162 -- , init
163 , splitAt -- spanN
164 -- , splitIn -- sessionN
166 -- ** Parallel Distribution
167 , teeWith
168 , tee
169 , teeWithFst
170 , teeWithMin
171 , distribute
172 -- , distributeFst
173 -- , distributeMin
175 -- ** Parallel Alternative
176 , shortest
177 , longest
179 -- ** Partitioning
180 , partitionByM
181 , partitionByFstM
182 , partitionByMinM
183 , partitionBy
184 , partition
186 -- ** Demultiplexing
187 -- | Direct values in the input stream to different folds using an n-ary
188 -- fold selector.
189 , demux -- XXX rename this to demux_
190 , demuxWith
191 , demuxDefault -- XXX rename this to demux
192 , demuxDefaultWith
193 -- , demuxWithSel
194 -- , demuxWithMin
196 -- ** Classifying
197 -- | In an input stream of key value pairs fold values for different keys
198 -- in individual output buckets using the given fold.
199 , classify
200 , classifyWith
201 -- , classifyWithSel
202 -- , classifyWithMin
204 -- ** Unzipping
205 , unzip
206 -- These two can be expressed using lmap/lmapM and unzip
207 , unzipWith
208 , unzipWithM
209 , unzipWithFstM
210 , unzipWithMinM
212 -- ** Zipping
213 , zipWithM
214 , zip
216 -- ** Splitting
217 , many
218 , intervalsOf
219 , chunksOf
220 , chunksBetween
222 -- ** Nesting
223 , concatSequence
224 , concatMap
226 -- * Running Partially
227 , initialize
228 , runStep
229 , duplicate
231 -- * Fold2
232 , drainBy2
234 -- * Deprecated
235 , sequence
236 , mapM
237 )
238where
240import Control.Monad (void)
241import Data.Bifunctor (first)
242import Data.Functor.Identity (Identity(..))
243import Data.Int (Int64)
244import Data.Map.Strict (Map)
245import Data.Maybe (isJust, fromJust)
246#if __GLASGOW_HASKELL__ < 804
247import Data.Semigroup (Semigroup((<>)))
248#endif
249import Streamly.Internal.Data.Either.Strict
250 (Either'(..), fromLeft', fromRight', isLeft', isRight')
251import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
252import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
253import Streamly.Internal.Data.Stream.Serial (SerialT)
255import qualified Data.Map.Strict as Map
256import qualified Streamly.Internal.Data.Pipe.Type as Pipe
257import qualified Streamly.Internal.Data.Stream.IsStream.Enumeration as Stream
258import qualified Streamly.Internal.Data.Stream.StreamK as K
259import qualified Prelude
261import Prelude hiding
262 ( filter, foldl1, drop, dropWhile, take, takeWhile, zipWith
263 , foldl, foldr, map, mapM_, sequence, all, any, sum, product, elem
264 , notElem, maximum, minimum, head, last, tail, length, null
265 , reverse, iterate, init, and, or, lookup, (!!)
266 , scanl, scanl1, replicate, concatMap, mconcat, foldMap, unzip
267 , span, splitAt, break, mapM, zip)
268import Streamly.Internal.Data.Fold.Type
270-- $setup
271-- >>> :m
272-- >>> import Prelude hiding (break, map, span, splitAt)
273-- >>> import qualified Streamly.Prelude as Stream
274-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream (parse, foldMany)
275-- >>> import qualified Streamly.Data.Fold as Fold
276-- >>> import qualified Streamly.Internal.Data.Fold as Fold
277-- >>> import qualified Streamly.Internal.Data.Parser as Parser
278-- >>> import Data.IORef (newIORef, readIORef, writeIORef)
280------------------------------------------------------------------------------
281-- hoist
282------------------------------------------------------------------------------
284-- | Change the underlying monad of a fold
285--
286-- /Pre-release/
287hoist :: (forall x. m x -> n x) -> Fold m a b -> Fold n a b
288hoist f (Fold step initial extract) =
289 Fold (\x a -> f $ step x a) (f initial) (f . extract)
291-- | Adapt a pure fold to any monad
292--
293-- > generally = Fold.hoist (return . runIdentity)
294--
295-- /Pre-release/
296generally :: Monad m => Fold Identity a b -> Fold m a b
297generally = hoist (return . runIdentity)
299------------------------------------------------------------------------------
300-- Transformations on fold inputs
301------------------------------------------------------------------------------
303-- | Flatten the monadic output of a fold to pure output.
304--
305-- @since 0.7.0
306{-# DEPRECATED sequence "Use \"rmapM id\" instead" #-}
307{-# INLINE sequence #-}
308sequence :: Monad m => Fold m a (m b) -> Fold m a b
309sequence = rmapM id
311-- | Map a monadic function on the output of a fold.
312--
313-- @since 0.7.0
314{-# DEPRECATED mapM "Use rmapM instead" #-}
315{-# INLINE mapM #-}
316mapM :: Monad m => (b -> m c) -> Fold m a b -> Fold m a c
317mapM = rmapM
319-- | @mapMaybe f fold@ maps a 'Maybe' returning function @f@ on the input of
320-- the fold, filters out 'Nothing' elements, and return the values extracted
321-- from 'Just'.
322--
323-- >>> f x = if even x then Just x else Nothing
324-- >>> fld = Fold.mapMaybe f Fold.toList
325-- >>> Stream.fold fld (Stream.enumerateFromTo 1 10)
326-- [2,4,6,8,10]
327--
328-- @since 0.8.0
329{-# INLINE mapMaybe #-}
330mapMaybe :: (Monad m) => (a -> Maybe b) -> Fold m b r -> Fold m a r
331mapMaybe f = lmap f . filter isJust . lmap fromJust
333------------------------------------------------------------------------------
334-- Transformations on fold inputs
335------------------------------------------------------------------------------
337-- rename to lpipe?
338--
339-- | Apply a transformation on a 'Fold' using a 'Pipe'.
340--
341-- /Pre-release/
342{-# INLINE transform #-}
343transform :: Monad m => Pipe m a b -> Fold m b c -> Fold m a c
344transform (Pipe pstep1 pstep2 pinitial) (Fold fstep finitial fextract) =
345 Fold step initial extract
347 where
349 initial = first (Tuple' pinitial) <$> finitial
351 step (Tuple' ps fs) x = do
352 r <- pstep1 ps x
353 go fs r
355 where
357 -- XXX use SPEC?
358 go acc (Pipe.Yield b (Consume ps')) = do
359 acc' <- fstep acc b
360 return
361 $ case acc' of
362 Partial s -> Partial $ Tuple' ps' s
363 Done b2 -> Done b2
364 go acc (Pipe.Yield b (Produce ps')) = do
365 acc' <- fstep acc b
366 r <- pstep2 ps'
367 case acc' of
368 Partial s -> go s r
369 Done b2 -> return $ Done b2
370 go acc (Pipe.Continue (Consume ps')) =
371 return $ Partial $ Tuple' ps' acc
372 go acc (Pipe.Continue (Produce ps')) = do
373 r <- pstep2 ps'
374 go acc r
376 extract (Tuple' _ fs) = fextract fs
378------------------------------------------------------------------------------
379-- Left folds
380------------------------------------------------------------------------------
382------------------------------------------------------------------------------
383-- Run Effects
384------------------------------------------------------------------------------
386-- |
387-- > drainBy f = lmapM f drain
388-- > drainBy = Fold.foldMapM (void . f)
389--
390-- Drain all input after passing it through a monadic function. This is the
391-- dual of mapM_ on stream producers.
392--
393-- See also: 'Streamly.Prelude.mapM_'
394--
395-- @since 0.7.0
396{-# INLINABLE drainBy #-}
397drainBy :: Monad m => (a -> m b) -> Fold m a ()
398drainBy f = lmapM f drain
400-- |
401--
402-- /Internal/
403{-# INLINABLE drainBy2 #-}
404drainBy2 :: Monad m => (a -> m b) -> Fold2 m c a ()
405drainBy2 f = Fold2 (const (void . f)) (\_ -> return ()) return
407-- | Extract the last element of the input stream, if any.
408--
409-- > last = fmap getLast $ Fold.foldMap (Last . Just)
410--
411-- @since 0.7.0
412{-# INLINABLE last #-}
413last :: Monad m => Fold m a (Maybe a)
414last = foldl1' (\_ x -> x)
416------------------------------------------------------------------------------
417-- To Summary
418------------------------------------------------------------------------------
420-- | Like 'length', except with a more general 'Num' return value
421--
422-- > genericLength = fmap getSum $ foldMap (Sum . const 1)
423--
424-- /Pre-release/
425{-# INLINE genericLength #-}
426genericLength :: (Monad m, Num b) => Fold m a b
427genericLength = foldl' (\n _ -> n + 1) 0
429-- | Determine the length of the input stream.
430--
431-- > length = fmap getSum $ Fold.foldMap (Sum . const 1)
432--
433-- @since 0.7.0
434{-# INLINE length #-}
435length :: Monad m => Fold m a Int
436length = genericLength
438-- | Determine the sum of all elements of a stream of numbers. Returns additive
439-- identity (@0@) when the stream is empty. Note that this is not numerically
440-- stable for floating point numbers.
441--
442-- > sum = fmap getSum $ Fold.foldMap Sum
443--
444-- @since 0.7.0
445{-# INLINE sum #-}
446sum :: (Monad m, Num a) => Fold m a a
447sum = foldl' (+) 0
449-- | Determine the product of all elements of a stream of numbers. Returns
450-- multiplicative identity (@1@) when the stream is empty. The fold terminates
451-- when it encounters (@0@) in its input.
452--
453-- Compare with @Fold.foldMap Product@.
454--
455-- @since 0.7.0
456-- /Since 0.8.0 (Added 'Eq' constraint)/
457{-# INLINE product #-}
458product :: (Monad m, Num a, Eq a) => Fold m a a
459product = mkFold_ step (Partial 1)
461 where
463 step x a =
464 if a == 0
465 then Done 0
466 else Partial $ x * a
468------------------------------------------------------------------------------
469-- To Summary (Maybe)
470------------------------------------------------------------------------------
472-- | Determine the maximum element in a stream using the supplied comparison
473-- function.
474--
475-- @since 0.7.0
476{-# INLINE maximumBy #-}
477maximumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
478maximumBy cmp = foldl1' max'
480 where
482 max' x y =
483 case cmp x y of
484 GT -> x
485 _ -> y
487-- |
488-- @
489-- maximum = Fold.maximumBy compare
490-- @
491--
492-- Determine the maximum element in a stream.
493--
494-- Compare with @Fold.foldMap Max@.
495--
496-- @since 0.7.0
497{-# INLINE maximum #-}
498maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
499maximum = foldl1' max
501-- | Computes the minimum element with respect to the given comparison function
502--
503-- @since 0.7.0
504{-# INLINE minimumBy #-}
505minimumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
506minimumBy cmp = foldl1' min'
508 where
510 min' x y =
511 case cmp x y of
512 GT -> y
513 _ -> x
515-- | Determine the minimum element in a stream using the supplied comparison
516-- function.
517--
518-- @
519-- minimum = 'minimumBy' compare
520-- @
521--
522-- Compare with @Fold.foldMap Min@.
523--
524-- @since 0.7.0
525{-# INLINE minimum #-}
526minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
527minimum = foldl1' min
529------------------------------------------------------------------------------
530-- To Summary (Statistical)
531------------------------------------------------------------------------------
533-- | Compute a numerically stable arithmetic mean of all elements in the input
534-- stream.
535--
536-- @since 0.7.0
537{-# INLINABLE mean #-}
538mean :: (Monad m, Fractional a) => Fold m a a
539mean = fmap done $ foldl' step begin
541 where
543 begin = Tuple' 0 0
545 step (Tuple' x n) y =
546 let n1 = n + 1
547 in Tuple' (x + (y - x) / n1) n1
549 done (Tuple' x _) = x
551-- | Compute a numerically stable (population) variance over all elements in
552-- the input stream.
553--
554-- @since 0.7.0
555{-# INLINABLE variance #-}
556variance :: (Monad m, Fractional a) => Fold m a a
557variance = fmap done $ foldl' step begin
559 where
561 begin = Tuple3' 0 0 0
563 step (Tuple3' n mean_ m2) x = Tuple3' n' mean' m2'
565 where
567 n' = n + 1
568 mean' = (n * mean_ + x) / (n + 1)
569 delta = x - mean_
570 m2' = m2 + delta * delta * n / (n + 1)
572 done (Tuple3' n _ m2) = m2 / n
574-- | Compute a numerically stable (population) standard deviation over all
575-- elements in the input stream.
576--
577-- @since 0.7.0
578{-# INLINABLE stdDev #-}
579stdDev :: (Monad m, Floating a) => Fold m a a
580stdDev = sqrt <$> variance
582-- | Compute an 'Int' sized polynomial rolling hash
583--
584-- > H = salt * k ^ n + c1 * k ^ (n - 1) + c2 * k ^ (n - 2) + ... + cn * k ^ 0
585--
586-- Where @c1@, @c2@, @cn@ are the elements in the input stream and @k@ is a
587-- constant.
588--
589-- This hash is often used in Rabin-Karp string search algorithm.
590--
591-- See https://en.wikipedia.org/wiki/Rolling_hash
592--
593-- @since 0.8.0
594{-# INLINABLE rollingHashWithSalt #-}
595rollingHashWithSalt :: (Monad m, Enum a) => Int64 -> Fold m a Int64
596rollingHashWithSalt = foldl' step
598 where
600 k = 2891336453 :: Int64
602 step cksum a = cksum * k + fromIntegral (fromEnum a)
604-- | A default salt used in the implementation of 'rollingHash'.
605{-# INLINE defaultSalt #-}
606defaultSalt :: Int64
607defaultSalt = -2578643520546668380
609-- | Compute an 'Int' sized polynomial rolling hash of a stream.
610--
611-- > rollingHash = Fold.rollingHashWithSalt defaultSalt
612--
613-- @since 0.8.0
614{-# INLINABLE rollingHash #-}
615rollingHash :: (Monad m, Enum a) => Fold m a Int64
616rollingHash = rollingHashWithSalt defaultSalt
618-- | Compute an 'Int' sized polynomial rolling hash of the first n elements of
619-- a stream.
620--
621-- > rollingHashFirstN = Fold.take n Fold.rollingHash
622--
623-- /Pre-release/
624{-# INLINABLE rollingHashFirstN #-}
625rollingHashFirstN :: (Monad m, Enum a) => Int -> Fold m a Int64
626rollingHashFirstN n = take n rollingHash
628------------------------------------------------------------------------------
629-- Monoidal left folds
630------------------------------------------------------------------------------
632-- | Append the elements of an input stream to a provided starting value.
633--
634-- >>> Stream.fold (Fold.sconcat 10) (Stream.map Data.Monoid.Sum $ Stream.enumerateFromTo 1 10)
635-- Sum {getSum = 65}
636--
637-- @
638-- sconcat = Fold.foldl' (<>)
639-- @
640--
641-- @since 0.8.0
642{-# INLINE sconcat #-}
643sconcat :: (Monad m, Semigroup a) => a -> Fold m a a
644sconcat = foldl' (<>)
646-- | Fold an input stream consisting of monoidal elements using 'mappend'
647-- and 'mempty'.
648--
649-- >>> Stream.fold Fold.mconcat (Stream.map Data.Monoid.Sum $ Stream.enumerateFromTo 1 10)
650-- Sum {getSum = 55}
651--
652-- > mconcat = Fold.sconcat mempty
653--
654-- @since 0.7.0
655{-# INLINE mconcat #-}
656mconcat ::
657 ( Monad m
658#if !MIN_VERSION_base(4,11,0)
659 , Semigroup a
660#endif
661 , Monoid a) => Fold m a a
662mconcat = sconcat mempty
664-- |
665-- > foldMap f = Fold.lmap f Fold.mconcat
666--
667-- Make a fold from a pure function that folds the output of the function
668-- using 'mappend' and 'mempty'.
669--
670-- >>> Stream.fold (Fold.foldMap Data.Monoid.Sum) $ Stream.enumerateFromTo 1 10
671-- Sum {getSum = 55}
672--
673-- @since 0.7.0
674{-# INLINABLE foldMap #-}
675foldMap :: (Monad m, Monoid b
676#if !MIN_VERSION_base(4,11,0)
677 , Semigroup b
678#endif
679 ) => (a -> b) -> Fold m a b
680foldMap f = lmap f mconcat
682-- |
683-- > foldMapM f = Fold.lmapM f Fold.mconcat
684--
685-- Make a fold from a monadic function that folds the output of the function
686-- using 'mappend' and 'mempty'.
687--
688-- >>> Stream.fold (Fold.foldMapM (return . Data.Monoid.Sum)) $ Stream.enumerateFromTo 1 10
689-- Sum {getSum = 55}
690--
691-- @since 0.7.0
692{-# INLINABLE foldMapM #-}
693foldMapM :: (Monad m, Monoid b) => (a -> m b) -> Fold m a b
694foldMapM act = foldlM' step (pure mempty)
696 where
698 step m a = do
699 m' <- act a
700 return $! mappend m m'
702------------------------------------------------------------------------------
703-- To Containers
704------------------------------------------------------------------------------
706-- $toListRev
707-- This is more efficient than 'Streamly.Internal.Data.Fold.toList'. toList is
708-- exactly the same as reversing the list after 'toListRev'.
710-- | Buffers the input stream to a list in the reverse order of the input.
711--
712-- > toListRev = Fold.foldl' (flip (:)) []
713--
714-- /Warning!/ working on large lists accumulated as buffers in memory could be
715-- very inefficient, consider using "Streamly.Array" instead.
716--
717-- @since 0.8.0
719-- xn : ... : x2 : x1 : []
720{-# INLINABLE toListRev #-}
721toListRev :: Monad m => Fold m a [a]
722toListRev = foldl' (flip (:)) []
724------------------------------------------------------------------------------
725-- Partial Folds
726------------------------------------------------------------------------------
728-- | A fold that drains the first n elements of its input, running the effects
729-- and discarding the results.
730--
731-- > drainN n = Fold.take n Fold.drain
732--
733-- /Pre-release/
734{-# INLINABLE drainN #-}
735drainN :: Monad m => Int -> Fold m a ()
736drainN n = take n drain
738------------------------------------------------------------------------------
739-- To Elements
740------------------------------------------------------------------------------
742-- | Like 'index', except with a more general 'Integral' argument
743--
744-- /Pre-release/
745{-# INLINABLE genericIndex #-}
746genericIndex :: (Integral i, Monad m) => i -> Fold m a (Maybe a)
747genericIndex i = mkFold step (Partial 0) (const Nothing)
749 where
751 step j a =
752 if i == j
753 then Done $ Just a
754 else Partial (j + 1)
756-- | Lookup the element at the given index.
757--
758-- See also: 'Streamly.Prelude.!!'
759--
760-- @since 0.7.0
761{-# INLINABLE index #-}
762index :: Monad m => Int -> Fold m a (Maybe a)
763index = genericIndex
765-- | Extract the first element of the stream, if any.
766--
767-- @since 0.7.0
768{-# INLINABLE head #-}
769head :: Monad m => Fold m a (Maybe a)
770head = mkFold_ (const (Done . Just)) (Partial Nothing)
772-- | Returns the first element that satisfies the given predicate.
773--
774-- @since 0.7.0
775{-# INLINABLE find #-}
776find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
777find predicate = mkFold step (Partial ()) (const Nothing)
779 where
781 step () a =
782 if predicate a
783 then Done (Just a)
784 else Partial ()
786-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
787-- first pair where the key equals the given value @a@.
788--
789-- > lookup = snd <$> Fold.find ((==) . fst)
790--
791-- @since 0.7.0
792{-# INLINABLE lookup #-}
793lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
794lookup a0 = mkFold step (Partial ()) (const Nothing)
796 where
798 step () (a, b) =
799 if a == a0
800 then Done $ Just b
801 else Partial ()
803-- | Returns the first index that satisfies the given predicate.
804--
805-- @since 0.7.0
806{-# INLINABLE findIndex #-}
807findIndex :: Monad m => (a -> Bool) -> Fold m a (Maybe Int)
808findIndex predicate = mkFold step (Partial 0) (const Nothing)
810 where
812 step i a =
813 if predicate a
814 then Done $ Just i
815 else Partial (i + 1)
817-- | Returns the first index where a given value is found in the stream.
818--
819-- > elemIndex a = Fold.findIndex (== a)
820--
821-- @since 0.7.0
822{-# INLINABLE elemIndex #-}
823elemIndex :: (Eq a, Monad m) => a -> Fold m a (Maybe Int)
824elemIndex a = findIndex (a ==)
826------------------------------------------------------------------------------
827-- To Boolean
828------------------------------------------------------------------------------
830-- | Return 'True' if the input stream is empty.
831--
832-- > null = fmap isJust Fold.head
833--
834-- @since 0.7.0
835{-# INLINABLE null #-}
836null :: Monad m => Fold m a Bool
837null = mkFold (\() _ -> Done False) (Partial ()) (const True)
839-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
840--
841-- >>> Stream.fold (Fold.any (== 0)) $ Stream.fromList [1,0,1]
842-- True
843--
844-- > any p = Fold.lmap p Fold.or
845--
846-- @since 0.7.0
847{-# INLINE any #-}
848any :: Monad m => (a -> Bool) -> Fold m a Bool
849any predicate = mkFold_ step initial
851 where
853 initial = Partial False
855 step _ a =
856 if predicate a
857 then Done True
858 else Partial False
860-- | Return 'True' if the given element is present in the stream.
861--
862-- > elem a = Fold.any (== a)
863--
864-- @since 0.7.0
865{-# INLINABLE elem #-}
866elem :: (Eq a, Monad m) => a -> Fold m a Bool
867elem a = any (a ==)
869-- | Returns 'True' if all elements of a stream satisfy a predicate.
870--
871-- >>> Stream.fold (Fold.all (== 0)) $ Stream.fromList [1,0,1]
872-- False
873--
874-- > all p = Fold.lmap p Fold.and
875--
876-- @since 0.7.0
877{-# INLINABLE all #-}
878all :: Monad m => (a -> Bool) -> Fold m a Bool
879all predicate = mkFold_ step initial
881 where
883 initial = Partial True
885 step _ a =
886 if predicate a
887 then Partial True
888 else Done False
890-- | Returns 'True' if the given element is not present in the stream.
891--
892-- > notElem a = Fold.all (/= a)
893--
894-- @since 0.7.0
895{-# INLINABLE notElem #-}
896notElem :: (Eq a, Monad m) => a -> Fold m a Bool
897notElem a = all (a /=)
899-- | Returns 'True' if all elements are 'True', 'False' otherwise
900--
901-- > and = Fold.all (== True)
902--
903-- @since 0.7.0
904{-# INLINE and #-}
905and :: Monad m => Fold m Bool Bool
906and = all (== True)
908-- | Returns 'True' if any element is 'True', 'False' otherwise
909--
910-- > or = Fold.any (== True)
911--
912-- @since 0.7.0
913{-# INLINE or #-}
914or :: Monad m => Fold m Bool Bool
915or = any (== True)
917------------------------------------------------------------------------------
918-- Grouping/Splitting
919------------------------------------------------------------------------------
921------------------------------------------------------------------------------
922-- Grouping without looking at elements
923------------------------------------------------------------------------------
925------------------------------------------------------------------------------
926-- Binary APIs
927------------------------------------------------------------------------------
929-- | @splitAt n f1 f2@ composes folds @f1@ and @f2@ such that first @n@
930-- elements of its input are consumed by fold @f1@ and the rest of the stream
931-- is consumed by fold @f2@.
932--
933-- >>> let splitAt_ n xs = Stream.fold (Fold.splitAt n Fold.toList Fold.toList) $ Stream.fromList xs
934--
935-- >>> splitAt_ 6 "Hello World!"
936-- ("Hello ","World!")
937--
938-- >>> splitAt_ (-1) [1,2,3]
939-- ([],[1,2,3])
940--
941-- >>> splitAt_ 0 [1,2,3]
942-- ([],[1,2,3])
943--
944-- >>> splitAt_ 1 [1,2,3]
945-- ([1],[2,3])
946--
947-- >>> splitAt_ 3 [1,2,3]
948-- ([1,2,3],[])
949--
950-- >>> splitAt_ 4 [1,2,3]
951-- ([1,2,3],[])
952--
953-- > splitAt n f1 f2 = Fold.serialWith (,) (Fold.take n f1) f2
954--
955-- /Internal/
957{-# INLINE splitAt #-}
958splitAt
959 :: Monad m
960 => Int
961 -> Fold m a b
962 -> Fold m a c
963 -> Fold m a (b, c)
964splitAt n fld = serialWith (,) (take n fld)
966------------------------------------------------------------------------------
967-- Element Aware APIs
968------------------------------------------------------------------------------
969--
970------------------------------------------------------------------------------
971-- Binary APIs
972------------------------------------------------------------------------------
974-- Note: Keep this consistent with S.splitOn. In fact we should eliminate
975-- S.splitOn in favor of the fold.
976--
977-- XXX Use Fold.many instead once it is fixed.
978--
979-- | Like 'takeEndBy' but drops the element on which the predicate succeeds.
980--
981-- >>> Stream.fold (Fold.takeEndBy_ (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
982-- "hello"
983--
984-- >>> Stream.toList $ Stream.foldMany (Fold.takeEndBy_ (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
985-- ["hello","there"]
986--
987-- > Stream.splitOnSuffix p f = Stream.foldMany (Fold.takeEndBy_ p f)
988--
989-- See 'Streamly.Prelude.splitOnSuffix' for more details on splitting a
990-- stream using 'takeEndBy_'.
991--
992-- @since 0.8.0
993{-# INLINE takeEndBy_ #-}
994takeEndBy_ :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
995takeEndBy_ predicate (Fold fstep finitial fextract) =
996 Fold step finitial fextract
998 where
1000 step s a =
1001 if not (predicate a)
1002 then fstep s a
1003 else Done <$> fextract s
1005-- | Take the input, stop when the predicate succeeds taking the succeeding
1006-- element as well.
1008-- >>> Stream.fold (Fold.takeEndBy (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
1009-- "hello\n"
1011-- >>> Stream.toList $ Stream.foldMany (Fold.takeEndBy (== '\n') Fold.toList) $ Stream.fromList "hello\nthere\n"
1012-- ["hello\n","there\n"]
1014-- > Stream.splitWithSuffix p f = Stream.foldMany (Fold.takeEndBy p f)
1016-- See 'Streamly.Prelude.splitWithSuffix' for more details on splitting a
1017-- stream using 'takeEndBy'.
1019-- @since 0.8.0
1020{-# INLINE takeEndBy #-}
1021takeEndBy :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
1022takeEndBy predicate (Fold fstep finitial fextract) =
1023 Fold step finitial fextract
1025 where
1027 step s a = do
1028 res <- fstep s a
1029 if not (predicate a)
1030 then return res
1031 else do
1032 case res of
1033 Partial s1 -> Done <$> fextract s1
1034 Done b -> return $ Done b
1036------------------------------------------------------------------------------
1037-- Binary splitting on a separator
1038------------------------------------------------------------------------------
1041-- | Find the first occurrence of the specified sequence in the input stream
1042-- and break the input stream into two parts, the first part consisting of the
1043-- stream before the sequence and the second part consisting of the sequence
1044-- and the rest of the stream.
1046-- > let breakOn_ pat xs = S.fold (S.breakOn pat FL.toList FL.toList) $ S.fromList xs
1048-- >>> breakOn_ "dear" "Hello dear world!"
1049-- > ("Hello ","dear world!")
1051{-# INLINE breakOn #-}
1052breakOn :: Monad m => Array a -> Fold m a b -> Fold m a c -> Fold m a (b,c)
1053breakOn pat f m = undefined
1056------------------------------------------------------------------------------
1057-- Distributing
1058------------------------------------------------------------------------------
1060-- | Distribute one copy of the stream to each fold and zip the results.
1062-- @
1063-- |-------Fold m a b--------|
1064-- ---stream m a---| |---m (b,c)
1065-- |-------Fold m a c--------|
1066-- @
1067-- >>> Stream.fold (Fold.tee Fold.sum Fold.length) (Stream.enumerateFromTo 1.0 100.0)
1068-- (5050.0,100)
1070-- > tee = teeWith (,)
1072-- @since 0.7.0
1073{-# INLINE tee #-}
1074tee :: Monad m => Fold m a b -> Fold m a c -> Fold m a (b,c)
1075tee = teeWith (,)
1077-- XXX use "List" instead of "[]"?, use Array for output to scale it to a large
1078-- number of consumers? For polymorphic case a vector could be helpful. For
1079-- Storables we can use arrays. Will need separate APIs for those.
1081-- | Distribute one copy of the stream to each fold and collect the results in
1082-- a container.
1084-- @
1086-- |-------Fold m a b--------|
1087-- ---stream m a---| |---m [b]
1088-- |-------Fold m a b--------|
1089-- | |
1090-- ...
1091-- @
1093-- >>> Stream.fold (Fold.distribute [Fold.sum, Fold.length]) (Stream.enumerateFromTo 1 5)
1094-- [15,5]
1096-- > distribute = Prelude.foldr (Fold.teeWith (:)) (Fold.fromPure [])
1098-- This is the consumer side dual of the producer side 'sequence' operation.
1100-- Stops when all the folds stop.
1102-- @since 0.7.0
1103{-# INLINE distribute #-}
1104distribute :: Monad m => [Fold m a b] -> Fold m a [b]
1105distribute = Prelude.foldr (teeWith (:)) (fromPure [])
1107------------------------------------------------------------------------------
1108-- Partitioning
1109------------------------------------------------------------------------------
1111-- | Partition the input over two folds using an 'Either' partitioning
1112-- predicate.
1114-- @
1116-- |-------Fold b x--------|
1117-- -----stream m a --> (Either b c)----| |----(x,y)
1118-- |-------Fold c y--------|
1119-- @
1121-- Send input to either fold randomly:
1123-- @
1124-- > import System.Random (randomIO)
1125-- > randomly a = randomIO >>= \\x -> return $ if x then Left a else Right a
1126-- > Stream.fold (Fold.partitionByM randomly Fold.length Fold.length) (Stream.enumerateFromTo 1 100)
1127-- (59,41)
1128-- @
1130-- Send input to the two folds in a proportion of 2:1:
1132-- >>> :{
1133-- proportionately m n = do
1134-- ref <- newIORef $ cycle $ concat [replicate m Left, replicate n Right]
1135-- return $ \a -> do
1136-- r <- readIORef ref
1137-- writeIORef ref $ tail r
1138-- return $ Prelude.head r a
1139-- :}
1141-- >>> :{
1142-- main = do
1143-- f <- proportionately 2 1
1144-- r <- Stream.fold (Fold.partitionByM f Fold.length Fold.length) (Stream.enumerateFromTo (1 :: Int) 100)
1145-- print r
1146-- :}
1148-- >>> main
1149-- (67,33)
1152-- This is the consumer side dual of the producer side 'mergeBy' operation.
1154-- When one fold is done, any input meant for it is ignored until the other
1155-- fold is also done.
1157-- Stops when both the folds stop.
1159-- /See also: 'partitionByFstM' and 'partitionByMinM'./
1161-- /Pre-release/
1162{-# INLINE partitionByM #-}
1163partitionByM :: Monad m
1164 => (a -> m (Either b c)) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1165partitionByM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1166 Fold step begin done
1168 where
1170 begin = do
1171 resL <- beginL
1172 resR <- beginR
1173 return
1174 $ case resL of
1175 Partial sL ->
1176 Partial
1177 $ case resR of
1178 Partial sR -> RunBoth sL sR
1179 Done bR -> RunLeft sL bR
1180 Done bL ->
1181 case resR of
1182 Partial sR -> Partial $ RunRight bL sR
1183 Done bR -> Done (bL, bR)
1185 step (RunBoth sL sR) a = do
1186 r <- f a
1187 case r of
1188 Left b -> do
1189 res <- stepL sL b
1190 return
1191 $ Partial
1192 $ case res of
1193 Partial sres -> RunBoth sres sR
1194 Done bres -> RunRight bres sR
1195 Right c -> do
1196 res <- stepR sR c
1197 return
1198 $ Partial
1199 $ case res of
1200 Partial sres -> RunBoth sL sres
1201 Done bres -> RunLeft sL bres
1202 step (RunLeft sL bR) a = do
1203 r <- f a
1204 case r of
1205 Left b -> do
1206 res <- stepL sL b
1207 return
1208 $ case res of
1209 Partial sres -> Partial $ RunLeft sres bR
1210 Done bres -> Done (bres, bR)
1211 Right _ -> return $ Partial $ RunLeft sL bR
1212 step (RunRight bL sR) a = do
1213 r <- f a
1214 case r of
1215 Left _ -> return $ Partial $ RunRight bL sR
1216 Right c -> do
1217 res <- stepR sR c
1218 return
1219 $ case res of
1220 Partial sres -> Partial $ RunRight bL sres
1221 Done bres -> Done (bL, bres)
1223 done (RunBoth sL sR) = (,) <$> doneL sL <*> doneR sR
1224 done (RunLeft sL bR) = (,bR) <$> doneL sL
1225 done (RunRight bL sR) = (bL,) <$> doneR sR
1227-- | Similar to 'partitionByM' but terminates when the first fold terminates.
1230{-# INLINE partitionByFstM #-}
1231partitionByFstM :: Monad m
1232 => (a -> m (Either b c)) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1233partitionByFstM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1234 Fold step begin done
1236 where
1238 begin = do
1239 resL <- beginL
1240 resR <- beginR
1241 case resL of
1242 Partial sL -> return $
1243 case resR of
1244 Partial sR -> Partial $ RunFstBoth sL sR
1245 Done bR -> Partial $ RunFstLeft sL bR
1246 Done bL -> do
1247 case resR of
1248 Partial sR -> do
1249 bR <- doneR sR
1250 return $ Done (bL, bR)
1251 Done bR -> return $ Done (bL, bR)
1253 step (RunFstBoth sL sR) a = do
1254 r <- f a
1255 case r of
1256 Left b -> do
1257 res <- stepL sL b
1258 case res of
1259 Partial sres -> return $ Partial $ RunFstBoth sres sR
1260 Done bL -> do
1261 bR <- doneR sR
1262 return $ Done (bL, bR)
1264 Right c -> do
1265 res <- stepR sR c
1266 return
1267 $ Partial
1268 $ case res of
1269 Partial sres -> RunFstBoth sL sres
1270 Done bres -> RunFstLeft sL bres
1271 step (RunFstLeft sL bR) a = do
1272 r <- f a
1273 case r of
1274 Left b -> do
1275 res <- stepL sL b
1276 return
1277 $ case res of
1278 Partial sres -> Partial $ RunFstLeft sres bR
1279 Done bres -> Done (bres, bR)
1280 Right _ -> return $ Partial $ RunFstLeft sL bR
1282 done (RunFstBoth sL sR) = (,) <$> doneL sL <*> doneR sR
1284 done (RunFstLeft sL bR) = (,bR) <$> doneL sL
1286-- | Similar to 'partitionByM' but terminates when any fold terminates.
1289{-# INLINE partitionByMinM #-}
1290partitionByMinM :: Monad m =>
1291 (a -> m (Either b c)) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1292partitionByMinM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1293 Fold step begin done
1295 where
1297 begin = do
1298 resL <- beginL
1299 resR <- beginR
1300 case resL of
1301 Partial sL ->
1302 case resR of
1303 Partial sR -> return $ Partial $ Tuple' sL sR
1304 Done bR -> do
1305 bL <- doneL sL
1306 return $ Done (bL, bR)
1307 Done bL -> do
1308 case resR of
1309 Partial sR -> do
1310 bR <- doneR sR
1311 return $ Done (bL, bR)
1312 Done bR -> return $ Done (bL, bR)
1314 step (Tuple' sL sR) a = do
1315 r <- f a
1316 case r of
1317 Left b -> do
1318 res <- stepL sL b
1319 case res of
1320 Partial sres -> return $ Partial $ Tuple' sres sR
1321 Done bL -> do
1322 bR <- doneR sR
1323 return $ Done (bL, bR)
1325 Right c -> do
1326 res <- stepR sR c
1327 case res of
1328 Partial sres -> return $ Partial $ Tuple' sL sres
1329 Done bR -> do
1330 bL <- doneL sL
1331 return $ Done (bL, bR)
1333 done (Tuple' sL sR) = (,) <$> doneL sL <*> doneR sR
1335-- Note: we could use (a -> Bool) instead of (a -> Either b c), but the latter
1336-- makes the signature clearer as to which case belongs to which fold.
1337-- XXX need to check the performance in both cases.
1338-- | Same as 'partitionByM' but with a pure partition function.
1340-- Count even and odd numbers in a stream:
1342-- >>> :{
1343-- let f = Fold.partitionBy (\n -> if even n then Left n else Right n)
1344-- (fmap (("Even " ++) . show) Fold.length)
1345-- (fmap (("Odd " ++) . show) Fold.length)
1346-- in Stream.fold f (Stream.enumerateFromTo 1 100)
1347-- :}
1348-- ("Even 50","Odd 50")
1350-- /Pre-release/
1351{-# INLINE partitionBy #-}
1352partitionBy :: Monad m
1353 => (a -> Either b c) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1354partitionBy f = partitionByM (return . f)
1356-- | Compose two folds such that the combined fold accepts a stream of 'Either'
1357-- and routes the 'Left' values to the first fold and 'Right' values to the
1358-- second fold.
1360-- > partition = partitionBy id
1362-- @since 0.7.0
1363{-# INLINE partition #-}
1364partition :: Monad m
1365 => Fold m b x -> Fold m c y -> Fold m (Either b c) (x, y)
1366partition = partitionBy id
1369-- | Send one item to each fold in a round-robin fashion. This is the consumer
1370-- side dual of producer side 'mergeN' operation.
1372-- partitionN :: Monad m => [Fold m a b] -> Fold m a [b]
1373-- partitionN fs = Fold step begin done
1376-- TODO Demultiplex an input element into a number of typed variants. We want
1377-- to statically restrict the target values within a set of predefined types,
1378-- an enumeration of a GADT. We also want to make sure that the Map contains
1379-- only those types and the full set of those types.
1381-- TODO Instead of the input Map it should probably be a lookup-table using an
1382-- array and not in GC memory. The same applies to the output Map as well.
1383-- However, that would only be helpful if we have a very large data structure,
1384-- need to measure and see how it scales.
1386-- This is the consumer side dual of the producer side 'mux' operation (XXX to
1387-- be implemented).
1389-- | Split the input stream based on a key field and fold each split using a
1390-- specific fold collecting the results in a map from the keys to the results.
1391-- Useful for cases like protocol handlers to handle different type of packets
1392-- using different handlers.
1394-- @
1396-- |-------Fold m a b
1397-- -----stream m a-----Map-----|
1398-- |-------Fold m a b
1399-- |
1400-- ...
1401-- @
1403-- Any input that does not map to a fold in the input Map is silently ignored.
1405-- > demuxWith f kv = fmap fst $ demuxDefaultWith f kv drain
1407-- /Pre-release/
1409{-# INLINE demuxWith #-}
1410demuxWith :: (Monad m, Ord k)
1411 => (a -> (k, a')) -> Map k (Fold m a' b) -> Fold m a (Map k b)
1412demuxWith f kv = fmap fst $ demuxDefaultWith f kv drain
1414-- | Fold a stream of key value pairs using a map of specific folds for each
1415-- key into a map from keys to the results of fold outputs of the corresponding
1416-- values.
1418-- >>> import qualified Data.Map
1419-- >>> :{
1420-- let table = Data.Map.fromList [("SUM", Fold.sum), ("PRODUCT", Fold.product)]
1421-- input = Stream.fromList [("SUM",1),("PRODUCT",2),("SUM",3),("PRODUCT",4)]
1422-- in Stream.fold (Fold.demux table) input
1423-- :}
1424-- fromList [("PRODUCT",8),("SUM",4)]
1426-- > demux = demuxWith id
1428-- /Pre-release/
1429{-# INLINE demux #-}
1430demux :: (Monad m, Ord k)
1431 => Map k (Fold m a b) -> Fold m (k, a) (Map k b)
1432demux = demuxWith id
1434data DemuxState s b doneMap runMap =
1435 DemuxMapAndDefault !s !doneMap !runMap
1436 | DemuxOnlyMap b !doneMap !runMap
1437 | DemuxOnlyDefault s !doneMap
1439-- | Like 'demuxWith' but uses a default catchall fold to handle inputs which
1440-- do not have a specific fold in the map to handle them.
1442-- If any fold in the map stops, inputs meant for that fold are sent to the
1443-- catchall fold. If the catchall fold stops then inputs that do not match any
1444-- fold are ignored.
1446-- Stops when all the folds, including the catchall fold, stop.
1448-- /Pre-release/
1450{-# INLINE demuxDefaultWith #-}
1451demuxDefaultWith :: (Monad m, Ord k)
1452 => (a -> (k, a'))
1453 -> Map k (Fold m a' b)
1454 -> Fold m (k, a') c
1455 -> Fold m a (Map k b, c)
1456demuxDefaultWith f kv (Fold dstep dinitial dextract) =
1457 Fold step initial extract
1459 where
1461 initial = do
1462 let runInit (Fold step1 initial1 done1) = do
1463 r <- initial1
1464 return
1465 $ case r of
1466 Partial _ -> Right' (Fold step1 (return r) done1)
1467 Done b -> Left' b
1469 -- initialize folds in the kv map and separate the ones that are done
1470 -- from running ones
1471 kv1 <- Prelude.mapM runInit kv
1472 let runMap = Map.map fromRight' $ Map.filter isRight' kv1
1473 doneMap = Map.map fromLeft' $ Map.filter isLeft' kv1
1475 -- Run the default fold, and decide the next state based on its result
1476 dres <- dinitial
1477 return
1478 $ case dres of
1479 Partial s ->
1480 Partial
1481 $ if Map.size runMap > 0
1482 then DemuxMapAndDefault s doneMap runMap
1483 else DemuxOnlyDefault s doneMap
1484 Done b ->
1485 if Map.size runMap > 0
1486 then Partial $ DemuxOnlyMap b doneMap runMap
1487 else Done (doneMap, b)
1489 {-# INLINE runFold #-}
1490 runFold fPartial fDone doneMap runMap (Fold step1 initial1 done1) k a1 = do
1491 resi <- initial1
1492 case resi of
1493 Partial st -> do
1494 res <- step1 st a1
1495 return $ case res of
1496 Partial s ->
1497 let fld = Fold step1 (return $ Partial s) done1
1498 runMap1 = Map.insert k fld runMap
1499 in Partial $ fPartial doneMap runMap1
1500 Done b -> do
1501 let runMap1 = Map.delete k runMap
1502 doneMap1 = Map.insert k b doneMap
1503 if Map.size runMap1 == 0
1504 then fDone doneMap1
1505 else Partial $ fPartial doneMap1 runMap1
1506 Done _ -> error "Bug: demuxDefaultWith: Done fold"
1508 step (DemuxMapAndDefault dacc doneMap runMap) a = do
1509 let (k, a1) = f a
1510 case Map.lookup k runMap of
1511 Nothing -> do
1512 res <- dstep dacc (k, a1)
1513 return
1514 $ Partial
1515 $ case res of
1516 Partial s -> DemuxMapAndDefault s doneMap runMap
1517 Done b -> DemuxOnlyMap b doneMap runMap
1518 Just fld ->
1519 runFold
1520 (DemuxMapAndDefault dacc)
1521 (Partial . DemuxOnlyDefault dacc)
1522 doneMap runMap fld k a1
1524 step (DemuxOnlyMap dval doneMap runMap) a = do
1525 let (k, a1) = f a
1526 case Map.lookup k runMap of
1527 Nothing -> return $ Partial $ DemuxOnlyMap dval doneMap runMap
1528 Just fld ->
1529 runFold
1530 (DemuxOnlyMap dval)
1531 (Done . (, dval))
1532 doneMap runMap fld k a1
1533 step (DemuxOnlyDefault dacc doneMap) a = do
1534 let (k, a1) = f a
1535 res <- dstep dacc (k, a1)
1536 return
1537 $ case res of
1538 Partial s -> Partial $ DemuxOnlyDefault s doneMap
1539 Done b -> Done (doneMap, b)
1541 runExtract (Fold _ initial1 done1) = do
1542 res <- initial1
1543 case res of
1544 Partial s -> done1 s
1545 Done b -> return b
1547 extract (DemuxMapAndDefault dacc doneMap runMap) = do
1548 b <- dextract dacc
1549 runMap1 <- Prelude.mapM runExtract runMap
1550 return (doneMap `Map.union` runMap1, b)
1551 extract (DemuxOnlyMap dval doneMap runMap) = do
1552 runMap1 <- Prelude.mapM runExtract runMap
1553 return (doneMap `Map.union` runMap1, dval)
1554 extract (DemuxOnlyDefault dacc doneMap) = do
1555 b <- dextract dacc
1556 return (doneMap, b)
1558-- |
1559-- > demuxDefault = demuxDefaultWith id
1561-- /Pre-release/
1562{-# INLINE demuxDefault #-}
1563demuxDefault :: (Monad m, Ord k)
1564 => Map k (Fold m a b) -> Fold m (k, a) b -> Fold m (k, a) (Map k b, b)
1565demuxDefault = demuxDefaultWith id
1567-- TODO If the data is large we may need a map/hashmap in pinned memory instead
1568-- of a regular Map. That may require a serializable constraint though. We can
1569-- have another API for that.
1571-- | Split the input stream based on a key field and fold each split using the
1572-- given fold. Useful for map/reduce, bucketizing the input in different bins
1573-- or for generating histograms.
1575-- >>> :{
1576-- let input = Stream.fromList [("ONE",1),("ONE",1.1),("TWO",2), ("TWO",2.2)]
1577-- in Stream.fold (Fold.classifyWith fst (Fold.map snd Fold.toList)) input
1578-- :}
1579-- fromList [("ONE",[1.0,1.1]),("TWO",[2.0,2.2])]
1581-- If the classifier fold stops for a particular key any further inputs in that
1582-- bucket are ignored.
1584-- /Stops: never/
1586-- /Pre-release/
1588{-# INLINE classifyWith #-}
1589classifyWith :: (Monad m, Ord k) => (a -> k) -> Fold m a b -> Fold m a (Map k b)
1590classifyWith f (Fold step1 initial1 extract1) =
1591 rmapM extract $ foldlM' step initial
1593 where
1595 initial = return Map.empty
1597 step kv a =
1598 case Map.lookup k kv of
1599 Nothing -> do
1600 x <- initial1
1601 case x of
1602 Partial s -> do
1603 r <- step1 s a
1604 return
1605 $ flip (Map.insert k) kv
1606 $ case r of
1607 Partial s1 -> Left' s1
1608 Done b -> Right' b
1609 Done b -> return $ Map.insert k (Right' b) kv
1610 Just x -> do
1611 case x of
1612 Left' s -> do
1613 r <- step1 s a
1614 return
1615 $ flip (Map.insert k) kv
1616 $ case r of
1617 Partial s1 -> Left' s1
1618 Done b -> Right' b
1619 Right' _ -> return kv
1621 where
1623 k = f a
1625 extract =
1626 Prelude.mapM
1627 (\case
1628 Left' s -> extract1 s
1629 Right' b -> return b)
1631-- | Given an input stream of key value pairs and a fold for values, fold all
1632-- the values belonging to each key. Useful for map/reduce, bucketizing the
1633-- input in different bins or for generating histograms.
1635-- >>> :{
1636-- let input = Stream.fromList [("ONE",1),("ONE",1.1),("TWO",2), ("TWO",2.2)]
1637-- in Stream.fold (Fold.classify Fold.toList) input
1638-- :}
1639-- fromList [("ONE",[1.0,1.1]),("TWO",[2.0,2.2])]
1641-- Same as:
1643-- > classify fld = Fold.classifyWith fst (lmap snd fld)
1645-- /Pre-release/
1646{-# INLINE classify #-}
1647classify :: (Monad m, Ord k) => Fold m a b -> Fold m (k, a) (Map k b)
1648classify fld = classifyWith fst (lmap snd fld)
1650------------------------------------------------------------------------------
1651-- Unzipping
1652------------------------------------------------------------------------------
1654-- | Like 'unzipWith' but with a monadic splitter function.
1656-- @unzipWithM k f1 f2 = lmapM k (unzip f1 f2)@
1658-- /Pre-release/
1659{-# INLINE unzipWithM #-}
1660unzipWithM :: Monad m
1661 => (a -> m (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
1662unzipWithM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1663 Fold step begin done
1665 where
1667 begin = do
1668 resL <- beginL
1669 resR <- beginR
1670 return
1671 $ case resL of
1672 Partial sL ->
1673 Partial
1674 $ case resR of
1675 Partial sR -> RunBoth sL sR
1676 Done bR -> RunLeft sL bR
1677 Done bL ->
1678 case resR of
1679 Partial sR -> Partial $ RunRight bL sR
1680 Done bR -> Done (bL, bR)
1682 step (RunBoth sL sR) a = do
1683 (b, c) <- f a
1684 resL <- stepL sL b
1685 resR <- stepR sR c
1686 case resL of
1687 Partial sresL ->
1688 return
1689 $ Partial
1690 $ case resR of
1691 Partial sresR -> RunBoth sresL sresR
1692 Done bresR -> RunLeft sresL bresR
1693 Done bresL ->
1694 return
1695 $ case resR of
1696 Partial sresR -> Partial $ RunRight bresL sresR
1697 Done bresR -> Done (bresL, bresR)
1698 step (RunLeft sL bR) a = do
1699 (b, _) <- f a
1700 resL <- stepL sL b
1701 return
1702 $ case resL of
1703 Partial sresL -> Partial $ RunLeft sresL bR
1704 Done bresL -> Done (bresL, bR)
1705 step (RunRight bL sR) a = do
1706 (_, c) <- f a
1707 resR <- stepR sR c
1708 return
1709 $ case resR of
1710 Partial sresR -> Partial $ RunRight bL sresR
1711 Done bresR -> Done (bL, bresR)
1713 done (RunBoth sL sR) = (,) <$> doneL sL <*> doneR sR
1714 done (RunLeft sL bR) = (,bR) <$> doneL sL
1715 done (RunRight bL sR) = (bL,) <$> doneR sR
1717-- | Similar to 'unzipWithM' but terminates when the first fold terminates.
1720{-# INLINE unzipWithFstM #-}
1721unzipWithFstM :: Monad m =>
1722 (a -> m (b, c)) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1723unzipWithFstM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1724 Fold step begin done
1726 where
1728 begin = do
1729 resL <- beginL
1730 resR <- beginR
1731 case resL of
1732 Partial sL -> return $ Partial $
1733 case resR of
1734 Partial sR -> RunFstBoth sL sR
1735 Done bR -> RunFstLeft sL bR
1736 Done bL -> do
1737 case resR of
1738 Partial sR -> do
1739 bR <- doneR sR
1740 return $ Done (bL, bR)
1741 Done bR -> return $ Done (bL, bR)
1743 step (RunFstBoth sL sR) a = do
1744 (b, c) <- f a
1745 resL <- stepL sL b
1746 resR <- stepR sR c
1747 case resL of
1748 Partial sresL -> return $ Partial $
1749 case resR of
1750 Partial sresR -> RunFstBoth sresL sresR
1751 Done bresR -> RunFstLeft sresL bresR
1752 Done bL -> do
1753 case resR of
1754 Partial sresR -> do
1755 bR <- doneR sresR
1756 return $ Done (bL, bR)
1757 Done bR -> return $ Done (bL, bR)
1759 step (RunFstLeft sL bR) a = do
1760 (b, _) <- f a
1761 resL <- stepL sL b
1762 return
1763 $ case resL of
1764 Partial sresL -> Partial $ RunFstLeft sresL bR
1765 Done bresL -> Done (bresL, bR)
1767 done (RunFstBoth sL sR) = (,) <$> doneL sL <*> doneR sR
1768 done (RunFstLeft sL bR) = (,bR) <$> doneL sL
1770-- | Similar to 'unzipWithM' but terminates when any fold terminates.
1773{-# INLINE unzipWithMinM #-}
1774unzipWithMinM :: Monad m =>
1775 (a -> m (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
1776unzipWithMinM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1777 Fold step begin done
1779 where
1781 begin = do
1782 resL <- beginL
1783 resR <- beginR
1784 case resL of
1785 Partial sL ->
1786 case resR of
1787 Partial sR -> return $ Partial $ Tuple' sL sR
1788 Done bR -> do
1789 bL <- doneL sL
1790 return $ Done (bL, bR)
1791 Done bL -> do
1792 case resR of
1793 Partial sR -> do
1794 bR <- doneR sR
1795 return $ Done (bL, bR)
1796 Done bR -> return $ Done (bL, bR)
1798 step (Tuple' sL sR) a = do
1799 (b, c) <- f a
1800 resL <- stepL sL b
1801 resR <- stepR sR c
1802 case resL of
1803 Partial sresL ->
1804 case resR of
1805 Partial sresR -> return $ Partial $ Tuple' sresL sresR
1806 Done bR -> do
1807 bL <- doneL sL
1808 return $ Done (bL, bR)
1809 Done bL -> do
1810 case resR of
1811 Partial sresR -> do
1812 bR <- doneR sresR
1813 return $ Done (bL, bR)
1814 Done bR -> return $ Done (bL, bR)
1816 done (Tuple' sL sR) = (,) <$> doneL sL <*> doneR sR
1818-- | Split elements in the input stream into two parts using a pure splitter
1819-- function, direct each part to a different fold and zip the results.
1821-- @unzipWith f fld1 fld2 = Fold.lmap f (Fold.unzip fld1 fld2)@
1823-- This fold terminates when both the input folds terminate.
1825-- /Pre-release/
1826{-# INLINE unzipWith #-}
1827unzipWith :: Monad m
1828 => (a -> (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
1829unzipWith f = unzipWithM (return . f)
1831-- | Send the elements of tuples in a stream of tuples through two different
1832-- folds.
1834-- @
1836-- |-------Fold m a x--------|
1837-- ---------stream of (a,b)--| |----m (x,y)
1838-- |-------Fold m b y--------|
1840-- @
1842-- > unzip = Fold.unzipWith id
1844-- This is the consumer side dual of the producer side 'zip' operation.
1846-- @since 0.7.0
1847{-# INLINE unzip #-}
1848unzip :: Monad m => Fold m a x -> Fold m b y -> Fold m (a,b) (x,y)
1849unzip = unzipWith id
1851------------------------------------------------------------------------------
1852-- Combining streams and folds - Zipping
1853------------------------------------------------------------------------------
1855-- | Zip a stream with the input of a fold using the supplied function.
1857-- /Unimplemented/
1859{-# INLINE zipWithM #-}
1860zipWithM :: -- Monad m =>
1861 (a -> b -> m c) -> t m a -> Fold m c x -> Fold m b x
1862zipWithM = undefined
1864-- | Zip a stream with the input of a fold.
1866-- /Unimplemented/
1868{-# INLINE zip #-}
1869zip :: Monad m => t m a -> Fold m (a, b) x -> Fold m b x
1870zip = zipWithM (curry return)
1872-- | Pair each element of a fold input with its index, starting from index 0.
1874-- /Unimplemented/
1875{-# INLINE indexed #-}
1876indexed :: forall m a b. Monad m => Fold m (Int, a) b -> Fold m a b
1877indexed = zip (Stream.enumerateFrom 0 :: SerialT m Int)
1879-- | Change the predicate function of a Fold from @a -> b@ to accept an
1880-- additional state input @(s, a) -> b@. Convenient to filter with an
1881-- addiitonal index or time input.
1883-- @
1884-- filterWithIndex = with indexed filter
1885-- filterWithAbsTime = with timestamped filter
1886-- filterWithRelTime = with timeIndexed filter
1887-- @
1889-- /Pre-release/
1890{-# INLINE with #-}
1891with ::
1892 (Fold m (s, a) b -> Fold m a b)
1893 -> (((s, a) -> c) -> Fold m (s, a) b -> Fold m (s, a) b)
1894 -> (((s, a) -> c) -> Fold m a b -> Fold m a b)
1895with f comb g = f . comb g . lmap snd
1897-- | @sampleFromthen offset stride@ samples the element at @offset@ index and
1898-- then every element at strides of @stride@.
1900-- /Unimplemented/
1901{-# INLINE sampleFromthen #-}
1902sampleFromthen :: Monad m => Int -> Int -> Fold m a b -> Fold m a b
1903sampleFromthen offset size =
1904 with indexed filter (\(i, _) -> (i + offset) `mod` size == 0)
1906------------------------------------------------------------------------------
1907-- Nesting
1908------------------------------------------------------------------------------
1910-- | @concatSequence f t@ applies folds from stream @t@ sequentially and
1911-- collects the results using the fold @f@.
1913-- /Unimplemented/
1915{-# INLINE concatSequence #-}
1916concatSequence ::
1917 -- IsStream t =>
1918 Fold m b c -> t (Fold m a b) -> Fold m a c
1919concatSequence _f _p = undefined
1921-- | Group the input stream into groups of elements between @low@ and @high@.
1922-- Collection starts in chunks of @low@ and then keeps doubling until we reach
1923-- @high@. Each chunk is folded using the provided fold function.
1925-- This could be useful, for example, when we are folding a stream of unknown
1926-- size to a stream of arrays and we want to minimize the number of
1927-- allocations.
1929-- NOTE: this would be an application of "many" using a terminating fold.
1931-- /Unimplemented/
1933{-# INLINE chunksBetween #-}
1934chunksBetween :: -- Monad m =>
1935 Int -> Int -> Fold m a b -> Fold m b c -> Fold m a c
1936chunksBetween _low _high _f1 _f2 = undefined
1938-- | A fold that buffers its input to a pure stream.
1940-- /Warning!/ working on large streams accumulated as buffers in memory could
1941-- be very inefficient, consider using "Streamly.Data.Array" instead.
1943-- > toStream = foldr K.cons K.nil
1945-- /Pre-release/
1946{-# INLINE toStream #-}
1947toStream :: Monad m => Fold m a (SerialT Identity a)
1948toStream = foldr K.cons K.nil
1950-- This is more efficient than 'toStream'. toStream is exactly the same as
1951-- reversing the stream after toStreamRev.
1953-- | Buffers the input stream to a pure stream in the reverse order of the
1954-- input.
1956-- > toStreamRev = foldl' (flip K.cons) K.nil
1958-- /Warning!/ working on large streams accumulated as buffers in memory could
1959-- be very inefficient, consider using "Streamly.Data.Array" instead.
1961-- /Pre-release/
1963-- xn : ... : x2 : x1 : []
1964{-# INLINABLE toStreamRev #-}
1965toStreamRev :: Monad m => Fold m a (SerialT Identity a)
1966toStreamRev = foldl' (flip K.cons) K.nil