@@ -0,0 +1,1781 @@
1+{-# LANGUAGE BangPatterns #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE RankNTypes #-}
5+{-# LANGUAGE RecordWildCards #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
9+-- Module : Streamly.Fold
10+-- Copyright : (c) 2019 Composewell Technologies
11+-- (c) 2013 Gabriel Gonzalez
13+-- Maintainer : harendra.kumar@gmail.com
14+-- Stability : experimental
17+-- This module is the consumer side dual of the "Streamly.Prelude" module. The
18+-- "Streamly.Prelude" module contains producer or stream generation side
19+-- compositions while this module contains consumer side or stream fold
20+-- composition. Both the modules are organized in the same way so that you can
21+-- easily find the corresponding operations.
23+-- Stream consumers are essentially left folds that can be composed in many
24+-- interesting ways. For example, a parsing applicative composition builds an
25+-- applicative parser, a distributing applicative fold composition distributes
26+-- the input to the constituent folds and then combines the outputs.
27+-- Similarly, a partitioning applicative can partition the input among the
28+-- constituent folds. There are many other ways to combine folds.
30+-- > import qualified Streamly.Fold as FL
33+-- A left fold is represented by the type 'Fold'. @Fold m a b@ folds an
34+-- input stream consisting of values of type @a@ to a structure of type
35+-- @b@. The fold can be run using 'foldl'' and an input stream.
37+-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
40+-- Also see the "Streamly.Sink" module that provides specialized left folds
41+-- that discard the outputs.
42+-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
72+ -- ** Full Folds (Monoidal)
77+ -- ** Full Folds (To Containers)
78+ -- , toStream -- experimental
79+ , toStreamRev -- experimental
82+ , toListRev -- experimental
99+ -- XXX these are slower than right folds even when full input is used
105+ -- * Transformations
106+ -- | Unlike stream producer types (e.g. @SerialT m a@) which have only
107+ -- output side, folds have an input side as well as an output side. In the
108+ -- type @Fold m a b@, the input type is @a@ and the output type is @b@.
109+ -- Transformations can be applied either on the input side or on the output
110+ -- side. The 'Functor' instance of a fold maps on the output of the fold:
112+ -- >>> FL.foldl' (fmap show FL.sum) (S.enumerateFromTo 1 100)
115+ -- However, the input side or contravariant transformations are more
116+ -- interesting for folds. The following sections describe the input
117+ -- transformation operations on a fold. The names of the operations are
118+ -- consistent with their covariant counterparts in "Streamly.Prelude", the
119+ -- only difference is that they are prefixed with 'l' which stands for
120+ -- 'left' assuming left side is the input side, notice that in @Fold m a b@
121+ -- the type variable @a@ is on the left side.
155+ -- ** Mapping Filters
159+ -- ** Scanning Filters
164+ -- | Insertion adds more elements to the stream.
173+ -- * Stream Splitting Operations
176+ -- | Spanning splits the input into two groups and applies two different
177+ -- folds on each group.
179+ -- Element unaware spanning
182+ -- Element aware spanning
191+ -- | Grouping splits the stream into groups and applies the supplied fold
194+ -- In imperative terms grouped folding can be considered as a nested loop
195+ -- where we loop over the stream to group elements and then loop over
196+ -- individual groups to fold them to a single value that is yielded in the
199+ -- Note that these grouping folds are true streaming folds that never
200+ -- accumulate the group in memory before folding, i.e. the group elements
201+ -- are consumed by the folds as they are yielded by the stream. Therefore,
202+ -- the whole computation runs in constant space.
203+ -- In contrast, we can simply use a scan on the stream to buffer the whole
204+ -- groups in memory and then map a fold on it to fold the groups. This kind
205+ -- of grouping and folding would not work well when the group size is big.
207+ -- Element unaware grouping
210+ -- Element aware grouping
213+ -- , groupsRollingBy
214+ , grouped -- XXX experimental
216+ -- ** Splitting by an Element
222+ -- ** Splitting on a Sequence
228+ -- Keeping the delimiters
233+ -- Splitting by multiple sequences
235+ -- , splitSuffixOnAny
236+ -- , splitPrefixOnAny
240+ -- The 'Applicative' instance of a distributing 'Fold' distributes one copy
241+ -- of the stream to each fold and combines the results using a function.
245+ -- |-------Fold m a b--------|
246+ -- ---stream m a---| |---m (b,c,...)
247+ -- |-------Fold m a c--------|
252+ -- To compute the average of numbers in a stream without going throught he
255+ -- >>> let avg = (/) <$> FL.sum <*> fmap fromIntegral FL.length
256+ -- >>> FL.foldl' avg (S.enumerateFromTo 1.0 100.0)
259+ -- The 'Semigroup' and 'Monoid' instances of a distributing fold distribute
260+ -- the input to both the folds and combines the outputs using Monoid or
261+ -- Semigroup instances of the output types:
263+ -- >>> import Data.Monoid (Sum)
264+ -- >>> FL.foldl' (FL.head <> FL.last) (fmap Sum $ S.enumerateFromTo 1.0 100.0)
265+ -- Just (Sum {getSum = 101.0})
267+ -- The 'Num', 'Floating', and 'Fractional' instances work in the same way.
274+ -- Direct items in the input stream to different folds using a function to
275+ -- select the fold. This is useful to demultiplex the input stream.
287+ , duplicate -- experimental
291+ -- | Scans that can be used to split and fold a stream using 'grouped'.
297+import Data.Functor.Identity (Identity)
298+import Foreign.Storable (Storable(..))
300+ hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
301+ foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
302+ notElem, maximum, minimum, head, last, tail, length, null,
303+ reverse, iterate, init, and, or, lookup, foldr1, (!!),
304+ scanl, scanl1, replicate, concatMap, mconcat, foldMap, unzip,
305+ span, splitAt, break)
307+import Streamly.Array (Array)
308+import Streamly.Fold.Types (Fold(..))
309+import Streamly.Streams.Serial (SerialT)
310+import Streamly.Streams.StreamK (IsStream())
312+import Streamly.Strict
314+import Streamly (MonadAsync)
315+import qualified Streamly.Array as A
316+import qualified Streamly.Prelude as S
317+import qualified Streamly.Streams.StreamD as D
318+import qualified Streamly.Streams.StreamK as K
319+import qualified Streamly.Streams.Prelude as P
323+-- We can use the left folds in this module instead of the folds in
324+-- "Streamly.Prelude". For example the following two ways of folding are
325+-- equivalent in functionality and performance,
327+-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
329+-- >>> S.sum (S.enumerateFromTo 1 100)
332+-- However, left folds are push type folds. That means we push the entire input
333+-- to a fold before we can get the output. Therefore, the performance is
334+-- equivalent only for full folds like 'sum' and 'length'. For partial folds
335+-- like 'head' or 'any' the folds in "Streamly.Prelude" may be much more
336+-- efficient because they are implemented as right folds that terminate as soon
337+-- as we get the result. Note that when a full fold is composed with a partial
338+-- fold in parallel the performance is not impacted as we anyway have to
339+-- consume the whole stream due to the full fold.
341+-- >>> S.head (1 `S.cons` undefined)
343+-- >>> FL.foldl' FL.head (1 `S.cons` undefined)
344+-- *** Exception: Prelude.undefined
346+-- However, we can wrap the fold in a scan to convert it into a lazy stream of
347+-- fold steps. We can then terminate the stream whenever we want. For example,
349+-- >>> S.toList $ S.take 1 $ FL.scanl' FL.head (1 `S.cons` undefined)
352+-- The following example extracts the input stream up to a point where the
353+-- running average of elements is no more than 10:
357+-- $ S.map (fromJust . fst)
358+-- $ S.takeWhile (\\(_,x) -> x <= 10)
359+-- $ FL.postscanl' ((,) \<$> FL.last \<*> avg) (S.enumerateFromTo 1.0 100.0)
362+-- [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]
365+------------------------------------------------------------------------------
367+------------------------------------------------------------------------------
369+-- | Fold a stream using the supplied monadic fold.
371+-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
375+{-# INLINE foldl' #-}
376+foldl' :: Monad m => Fold m a b -> SerialT m a -> m b
377+foldl' (Fold step begin done) = P.foldlMx' step begin done
379+------------------------------------------------------------------------------
380+-- Transformations on fold inputs
381+------------------------------------------------------------------------------
383+-- | @(lmap f fold)@ maps the function @f@ on the input of the fold.
385+-- >>> FL.foldl' (FL.lmap (\x -> x * x) FL.sum) (S.enumerateFromTo 1 100)
389+{-# INLINABLE lmap #-}
390+lmap :: (a -> b) -> Fold m b r -> Fold m a r
391+lmap f (Fold step begin done) = Fold step' begin done
393+ step' x a = step x (f a)
395+-- | @(lmapM f fold)@ maps the monadic function @f@ on the input of the fold.
398+{-# INLINABLE lmapM #-}
399+lmapM :: Monad m => (a -> m b) -> Fold m b r -> Fold m a r
400+lmapM f (Fold step begin done) = Fold step' begin done
402+ step' x a = f a >>= step x
404+------------------------------------------------------------------------------
406+------------------------------------------------------------------------------
408+-- | @_Fold1 step@ returns a new 'Fold' using just a step function that has the
409+-- same type for the accumulator and the element. The result type is the
410+-- accumulator type wrapped in 'Maybe'. The initial accumulator is retrieved
411+-- from the 'Foldable', the result is 'None' for empty containers.
412+{-# INLINABLE _Fold1 #-}
413+_Fold1 :: Monad m => (a -> a -> a) -> Fold m a (Maybe a)
414+_Fold1 step = Fold step_ (return Nothing') fromStrictMaybe
416+ step_ mx a = return $ Just' $
421+------------------------------------------------------------------------------
423+------------------------------------------------------------------------------
425+------------------------------------------------------------------------------
427+------------------------------------------------------------------------------
429+-- | A fold that drains all its input, running the effects and discarding the
433+{-# INLINABLE drain #-}
434+drain :: Monad m => Fold m a ()
435+drain = Fold step begin done
438+ step _ _ = return ()
441+-- | Extract the last element of the input stream, if any.
444+{-# INLINABLE last #-}
445+last :: Monad m => Fold m a (Maybe a)
446+last = _Fold1 (flip const)
448+------------------------------------------------------------------------------
450+------------------------------------------------------------------------------
452+-- | Like 'length', except with a more general 'Num' return value
455+{-# INLINABLE genericLength #-}
456+genericLength :: (Monad m, Num b) => Fold m a b
457+genericLength = Fold (\n _ -> return $ n + 1) (return 0) return
459+-- | Determine the length of the input stream.
462+{-# INLINABLE length #-}
463+length :: Monad m => Fold m a Int
464+length = genericLength
466+-- | Determine the sum of all elements of a stream of numbers. Returns additive
467+-- identity (@0@) when the stream is empty. Note that this is not numerically
468+-- stable for floating point numbers.
471+{-# INLINABLE sum #-}
472+sum :: (Monad m, Num a) => Fold m a a
473+sum = Fold (\x a -> return $ x + a) (return 0) return
475+-- | Determine the product of all elements of a stream of numbers. Returns
476+-- multiplicative identity (@1@) when the stream is empty.
479+{-# INLINABLE product #-}
480+product :: (Monad m, Num a) => Fold m a a
481+product = Fold (\x a -> return $ x * a) (return 1) return
483+------------------------------------------------------------------------------
484+-- To Summary (Maybe)
485+------------------------------------------------------------------------------
487+-- | Determine the maximum element in a stream using the supplied comparison
491+{-# INLINABLE maximumBy #-}
492+maximumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
493+maximumBy cmp = _Fold1 max'
495+ max' x y = case cmp x y of
501+-- maximum = 'maximumBy' compare
504+-- Determine the maximum element in a stream.
507+{-# INLINABLE maximum #-}
508+maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
511+-- | Computes the minimum element with respect to the given comparison function
512+{-# INLINABLE minimumBy #-}
513+minimumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
514+minimumBy cmp = _Fold1 min'
516+ min' x y = case cmp x y of
520+-- | Determine the minimum element in a stream using the supplied comparison
524+{-# INLINABLE minimum #-}
525+minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
528+------------------------------------------------------------------------------
529+-- To Summary (Statistical)
530+------------------------------------------------------------------------------
532+-- | Compute a numerically stable arithmetic mean of all elements in the input
536+{-# INLINABLE mean #-}
537+mean :: (Monad m, Fractional a) => Fold m a a
538+mean = Fold step (return begin) (return . done)
541+ step (Tuple' x n) y = return $
543+ in Tuple' (x + (y - x) / n') n'
544+ done (Tuple' x _) = x
546+-- | Compute a numerically stable (population) variance over all elements in
550+{-# INLINABLE variance #-}
551+variance :: (Monad m, Fractional a) => Fold m a a
552+variance = Fold step (return begin) (return . done)
554+ begin = Tuple3' 0 0 0
556+ step (Tuple3' n mean_ m2) x = return $ Tuple3' n' mean' m2'
559+ mean' = (n * mean_ + x) / (n + 1)
561+ m2' = m2 + delta * delta * n / (n + 1)
563+ done (Tuple3' n _ m2) = m2 / n
565+-- | Compute a numerically stable (population) standard deviation over all
566+-- elements in the input stream.
569+{-# INLINABLE stdDev #-}
570+stdDev :: (Monad m, Floating a) => Fold m a a
571+stdDev = sqrt variance
573+------------------------------------------------------------------------------
574+-- Monoidal left folds
575+------------------------------------------------------------------------------
577+-- | Fold an input stream consisting of monoidal elements using 'mappend'
580+-- > FL.foldl FL.mconcat (S.map Sum $ S.enumerateFromTo 1 10)
583+{-# INLINABLE mconcat #-}
584+mconcat :: (Monad m, Monoid a) => Fold m a a
585+mconcat = Fold (\x a -> return $ mappend x a) (return mempty) return
588+-- > foldMap f = map f mconcat
590+-- Make a fold from a pure function that folds the output of the function
591+-- using 'mappend' and 'mempty'.
593+-- > FL.foldl (FL.foldMap Sum) $ S.enumerateFromTo 1 10
596+{-# INLINABLE foldMap #-}
597+foldMap :: (Monad m, Monoid b) => (a -> b) -> Fold m a b
598+foldMap f = lmap f mconcat
601+-- > foldMapM f = mapM f mconcat
603+-- Make a fold from a monadic function that folds the output of the function
604+-- using 'mappend' and 'mempty'.
606+-- > FL.foldM (FL.foldMapM (return . Sum)) $ S.enumerateFromTo 1 10
609+{-# INLINABLE foldMapM #-}
610+foldMapM :: (Monad m, Monoid b) => (a -> m b) -> Fold m a b
611+foldMapM act = Fold step begin done
614+ begin = return mempty
617+ return $! mappend m m'
619+------------------------------------------------------------------------------
621+------------------------------------------------------------------------------
623+-- | Folds the input stream to a list.
625+-- /Warning!/ working on large lists accumulated as buffers in memory could be
626+-- very inefficient, consider using "Streamly.Array" instead.
630+-- id . (x1 :) . (x2 :) . (x3 :) . ... . (xn :) $ []
631+{-# INLINABLE _toList #-}
632+_toList :: Monad m => Fold m a [a]
633+_toList = Fold (\f x -> return $ f . (x :))
637+-- This is more efficient than 'toList'. toList is exactly the same as
638+-- reversing the list after toListRev.
640+-- | Buffers the input stream to a list in the reverse order of the input.
642+-- /Warning!/ working on large lists accumulated as buffers in memory could be
643+-- very inefficient, consider using "Streamly.Array" instead.
647+-- xn : ... : x2 : x1 : []
648+{-# INLINABLE toListRev #-}
649+toListRev :: Monad m => Fold m a [a]
650+toListRev = Fold (\xs x -> return $ x:xs) (return []) return
652+-- | A fold that buffers its input to a pure stream.
654+-- /Warning!/ working on large streams accumulated as buffers in memory could
655+-- be very inefficient, consider using "Streamly.Array" instead.
658+{-# INLINABLE _toStream #-}
659+_toStream :: Monad m => Fold m a (SerialT Identity a)
660+_toStream = Fold (\f x -> return $ f . (x `K.cons`))
662+ (return . ($ K.nil))
664+-- This is more efficient than 'toStream'. toStream is exactly the same as
665+-- reversing the stream after toStreamRev.
667+-- | Buffers the input stream to a pure stream in the reverse order of the
670+-- /Warning!/ working on large streams accumulated as buffers in memory could
671+-- be very inefficient, consider using "Streamly.Array" instead.
675+-- xn : ... : x2 : x1 : []
676+{-# INLINABLE toStreamRev #-}
677+toStreamRev :: Monad m => Fold m a (SerialT Identity a)
678+toStreamRev = Fold (\xs x -> return $ x `S.cons` xs) (return S.nil) return
680+------------------------------------------------------------------------------
682+------------------------------------------------------------------------------
684+------------------------------------------------------------------------------
686+------------------------------------------------------------------------------
688+-- | Like 'index', except with a more general 'Integral' argument
691+{-# INLINABLE genericIndex #-}
692+genericIndex :: (Integral i, Monad m) => i -> Fold m a (Maybe a)
693+genericIndex i = Fold step (return $ Left' 0) done
697+ Left' j -> if i == j
706+-- | Lookup the element at the given index.
709+{-# INLINABLE index #-}
710+index :: Monad m => Int -> Fold m a (Maybe a)
713+-- | Extract the first element of the stream, if any.
716+{-# INLINABLE head #-}
717+head :: Monad m => Fold m a (Maybe a)
720+-- | Returns the first element that satisfies the given predicate.
723+{-# INLINABLE find #-}
724+find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
725+find predicate = Fold step (return Nothing') fromStrictMaybe
729+ Nothing' -> if predicate a
734+-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
735+-- first pair where the key equals the given value @a@.
738+{-# INLINABLE lookup #-}
739+lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
740+lookup a0 = Fold step (return Nothing') fromStrictMaybe
742+ step x (a,b) = return $
744+ Nothing' -> if a == a0
749+-- | Convert strict 'Either'' to lazy 'Maybe'
750+{-# INLINABLE hush #-}
751+hush :: Either' a b -> Maybe b
752+hush (Left' _) = Nothing
753+hush (Right' b) = Just b
755+-- | Returns the first index that satisfies the given predicate.
758+{-# INLINABLE findIndex #-}
759+findIndex :: Monad m => (a -> Bool) -> Fold m a (Maybe Int)
760+findIndex predicate = Fold step (return $ Left' 0) (return . hush)
770+-- | Returns the first index where a given value is found in the stream.
773+{-# INLINABLE elemIndex #-}
774+elemIndex :: (Eq a, Monad m) => a -> Fold m a (Maybe Int)
775+elemIndex a = findIndex (a ==)
777+------------------------------------------------------------------------------
779+------------------------------------------------------------------------------
781+-- | Return 'True' if the input stream is empty.
784+{-# INLINABLE null #-}
785+null :: Monad m => Fold m a Bool
786+null = Fold (\_ _ -> return False) (return True) return
789+-- > any p = lmap p or
791+-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
794+{-# INLINABLE any #-}
795+any :: Monad m => (a -> Bool) -> Fold m a Bool
796+any predicate = Fold (\x a -> return $ x || predicate a) (return False) return
798+-- | Return 'True' if the given element is present in the stream.
801+{-# INLINABLE elem #-}
802+elem :: (Eq a, Monad m) => a -> Fold m a Bool
806+-- > all p = lmap p and
808+-- | Returns 'True' if all elements of a stream satisfy a predicate.
811+{-# INLINABLE all #-}
812+all :: Monad m => (a -> Bool) -> Fold m a Bool
813+all predicate = Fold (\x a -> return $ x && predicate a) (return True) return
815+-- | Returns 'True' if the given element is not present in the stream.
818+{-# INLINABLE notElem #-}
819+notElem :: (Eq a, Monad m) => a -> Fold m a Bool
820+notElem a = all (a /=)
822+-- | Returns 'True' if all elements are 'True', 'False' otherwise
825+{-# INLINABLE and #-}
826+and :: Monad m => Fold m Bool Bool
827+and = Fold (\x a -> return $ x && a) (return True) return
829+-- | Returns 'True' if any element is 'True', 'False' otherwise
833+or :: Monad m => Fold m Bool Bool
834+or = Fold (\x a -> return $ x || a) (return False) return
836+------------------------------------------------------------------------------
837+-- Scanning with a Fold
838+------------------------------------------------------------------------------
840+-- | Scan a stream using the given monadic fold.
843+{-# INLINE scanl' #-}
844+scanl' :: Monad m => Fold m a b -> SerialT m a -> SerialT m b
845+scanl' (Fold step begin done) = P.scanlMx' step begin done
847+-- | Postscan a stream using the given monadic fold.
850+{-# INLINE postscanl' #-}
851+postscanl' :: Monad m => Fold m a b -> SerialT m a -> SerialT m b
852+postscanl' (Fold step begin done) = P.postscanlMx' step begin done
856+------------------------------------------------------------------------------
858+------------------------------------------------------------------------------
860+-- | Include only those elements that pass a predicate.
862+-- >>> FL.foldl (lfilter (> 5) FL.sum) [1..10]
866+{-# INLINABLE lfilter #-}
867+lfilter :: Monad m => (a -> Bool) -> Fold m a r -> Fold m a r
868+lfilter f (Fold step begin done) = Fold step' begin done
870+ step' x a = if f a then step x a else return x
872+-- | Like 'lfilter' but with a monadic predicate.
875+{-# INLINABLE lfilterM #-}
876+lfilterM :: Monad m => (a -> m Bool) -> Fold m a r -> Fold m a r
877+lfilterM f (Fold step begin done) = Fold step' begin done
881+ if use then step x a else return x
883+-- | Take first 'n' elements from the stream and discard the rest.
886+{-# INLINABLE ltake #-}
887+ltake :: Monad m => Int -> Fold m a b -> Fold m a b
888+ltake n (Fold step initial done) = Fold step' initial' done'
890+ initial' = fmap (Tuple' 0) initial
891+ step' (Tuple' i r) a = do
895+ return $ Tuple' (i + 1) res
896+ else return $ Tuple' i r
897+ done' (Tuple' _ r) = done r
899+-- | Takes elements from the input as long as the predicate succeeds.
902+{-# INLINABLE ltakeWhile #-}
903+ltakeWhile :: Monad m => (a -> Bool) -> Fold m a b -> Fold m a b
904+ltakeWhile predicate (Fold step initial done) = Fold step' initial' done'
906+ initial' = fmap Left' initial
907+ step' (Left' r) a = do
909+ then fmap Left' $ step r a
910+ else return (Right' r)
911+ step' r _ = return r
912+ done' (Left' r) = done r
913+ done' (Right' r) = done r
915+------------------------------------------------------------------------------
916+-- Grouping/Splitting
917+------------------------------------------------------------------------------
919+------------------------------------------------------------------------------
920+-- Grouping without looking at elements
921+------------------------------------------------------------------------------
923+------------------------------------------------------------------------------
925+------------------------------------------------------------------------------
929+-- | Split the input stream into two groups at index @n@, the first group
930+-- consisting of elements from index @0@ to index @n - 1@ i.e. the stream
931+-- prefix of length @n@ and the second group consisting of the rest of the
940+splitAt n = undefined
943+------------------------------------------------------------------------------
945+------------------------------------------------------------------------------
947+-- | Group the input stream into groups of @n@ elements each and then fold each
948+-- group using the provided fold function.
950+-- >> S.toList $ FL.groupsOf 2 FL.sum (S.enumerateFromTo 1 10)
954+{-# INLINE groupsOf #-}
956+ :: (IsStream t, Monad m)
957+ => Int -> Fold m a b -> t m a -> t m b
958+groupsOf n f m = D.fromStreamD $ D.groupsOf n f (D.toStreamD m)
960+------------------------------------------------------------------------------
961+-- Element Aware APIs
962+------------------------------------------------------------------------------
964+------------------------------------------------------------------------------
966+------------------------------------------------------------------------------
969+-- | Break the input stream of type (a,Bool) into two groups, the first group
970+-- takes input as long as the boolean is True, the second group takes the rest
973+-- This is the most general spanning combinator, all others can be implemented
980+ -> Fold m (a, Bool) (b, c)
981+spanned f m = undefined
983+-- | Break the input stream into two groups, the first group takes the input as
984+-- long as the predicate applied to the first element of the stream and next
985+-- input element holds 'True', the second group takes the rest of the input.
992+spanBy cmp f1 f2 = undefined
995+-- > span p = spanBy (\_ x -> p x)
997+-- Break the input stream into two groups, the first group takes the input as
998+-- long as the predicate is 'True', the second group takes the rest of the
1006+span p = spanBy (\_ x -> p x)
1009+-- > break p = span (not . p)
1011+-- Break the input stream into two groups, the first group takes the input as
1012+-- long as the predicate is 'False', the second group takes the rest of the
1020+break p = span (not . p)
1022+-- | Like 'spanBy' but applies the predicate in a rolling fashion i.e.
1023+-- predicate is applied to the previous and the next input elements.
1026+ => (a -> a -> Bool)
1030+spanRollingBy cmp f1 f2 = undefined
1033+------------------------------------------------------------------------------
1035+------------------------------------------------------------------------------
1037+-- XXX should we use a strict pair?
1039+-- | The splitter returns True if the current element is the last element of
1040+-- the group, otherwise returns false.
1043+{-# INLINE grouped #-}
1045+ :: (IsStream t, Monad m)
1049+grouped f m = D.fromStreamD $ D.grouped f (D.toStreamD m)
1051+-- An example of a splitter to be used with grouped.
1052+_newline :: IsStream t => t m Char -> t m (Char,Bool)
1053+_newline m = S.foldrS (\x xs ->
1055+ then (x,True) `K.cons` xs
1056+ else (x,False) `K.cons` xs) K.nil m
1058+-- | Group by applying a predicate to the first element of the current group
1059+-- and the next element in the input stream. The next element is considered
1060+-- part of the current group if the predicate succeeds otherwise a new group
1063+-- >>> S.toList $ FL.groupsBy (==) FL.toList $ S.fromList [1,1,2,2]
1068+ :: (IsStream t, Monad m)
1069+ => (a -> a -> Bool)
1073+groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
1076+-- | Apply a predicate to each new element in the input stream and the last
1077+-- element of the current group. In other words, perform a rolling comparison
1078+-- between two successive elements in the stream. The new element is considered
1079+-- part of the current group if the predicate succeeds otherwise a new group
1082+ :: (IsStream t, Monad m)
1083+ => (a -> a -> Bool)
1087+groupsRollingBy cmp f m = undefined
1091+-- > groups = groupsBy (==)
1093+-- >>> S.toList $ FL.groups FL.toList $ S.fromList [1,1,2,2]
1097+groups :: (IsStream t, Monad m, Eq a) => Fold m a b -> t m a -> t m b
1098+groups = groupsBy (==)
1100+------------------------------------------------------------------------------
1101+-- Binary splitting on a separator
1102+------------------------------------------------------------------------------
1105+{-# INLINE breakOn #-}
1106+breakOn :: Monad m => Array a -> Fold m a b -> Fold m a c -> Fold m a (b,c)
1107+breakOn pat f m = undefined
1110+------------------------------------------------------------------------------
1111+-- N-ary split on a predicate
1112+------------------------------------------------------------------------------
1114+-- TODO: Use a Splitter configuration similar to the "split" package to make it
1115+-- possible to express all splitting combinations. In general, we can have
1116+-- infix/suffix/prefix/condensing of separators, dropping both leading/trailing
1117+-- separators. We can have a single split operation taking the splitter config
1120+-- | Split a stream on separator elements determined by a predicate, dropping
1121+-- the separator. Separators are not considered part of stream segments on
1122+-- either side of it instead they are treated as infixed between two stream
1123+-- segments. For example, with @.@ as separator, @"a.b.c"@ would be parsed as
1124+-- @["a","b","c"]@. When @.@ is in leading or trailing position it is still
1125+-- considered as infixed, treating the first or the last segment as empty. For
1126+-- example, @".a."@ would be parsed as @["","a",""]@. This operation is
1127+-- opposite of 'intercalate'.
1129+-- Let's use the following definition for illustration:
1131+-- > splitBy_ p xs = S.toList $ FL.splitBy p (FL.toList) (S.fromList xs)
1133+-- >>> splitBy_ (== '.') ""
1136+-- >>> splitBy_ (== '.') "."
1139+-- >>> splitBy_ (== '.') ".a"
1142+-- >>> splitBy_ (== '.') "a."
1145+-- >>> splitBy_ (== '.') "a.b"
1148+-- >>> splitBy_ (== '.') "a..b"
1152+{-# INLINE splitBy #-}
1154+ :: (IsStream t, Monad m)
1155+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1156+splitBy predicate f m =
1157+ D.fromStreamD $ D.splitBy predicate f (D.toStreamD m)
1159+-- | Like 'splitBy' but the separator is treated as part of the previous
1160+-- stream segment (suffix). Therefore, when the separator is in trailing
1161+-- position, no empty segment is considered to follow it. For example, @"a.b."@
1162+-- would be parsed as @["a","b"]@ instead of @["a","b",""]@ as in the case of
1165+-- > splitSuffixBy_ p xs = S.toList $ FL.splitSuffixBy p (FL.toList) (S.fromList xs)
1167+-- >>> splitSuffixBy_ (== '.') ""
1170+-- >>> splitSuffixBy_ (== '.') "."
1173+-- >>> splitSuffixBy_ (== '.') "a"
1176+-- >>> splitSuffixBy_ (== '.') ".a"
1179+-- >>> splitSuffixBy_ (== '.') "a."
1182+-- >>> splitSuffixBy_ (== '.') "a.b"
1185+-- >>> splitSuffixBy_ (== '.') "a.b."
1188+-- >>> splitSuffixBy_ (== '.') "a..b.."
1189+-- > ["a","","b",""]
1191+-- > lines = splitSuffixBy (== '\n')
1194+{-# INLINE splitSuffixBy #-}
1196+ :: (IsStream t, Monad m)
1197+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1198+splitSuffixBy predicate f m =
1199+ D.fromStreamD $ D.splitSuffixBy predicate f (D.toStreamD m)
1201+-- | Like 'splitBy' but ignores repeated separators or separators in leading
1202+-- or trailing position. Therefore, @"..a..b.."@ would be parsed as
1203+-- @["a","b"]@. In other words, it treats the input like words separated by
1204+-- whitespace elements determined by the predicate.
1206+-- > wordsBy' p xs = S.toList $ FL.wordsBy p (FL.toList) (S.fromList xs)
1208+-- >>> wordsBy' (== ',') ""
1211+-- >>> wordsBy' (== ',') ","
1214+-- >>> wordsBy' (== ',') ",a,,b,"
1217+-- > words = wordsBy isSpace
1220+{-# INLINE wordsBy #-}
1222+ :: (IsStream t, Monad m)
1223+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1224+wordsBy predicate f m =
1225+ D.fromStreamD $ D.wordsBy predicate f (D.toStreamD m)
1227+-- XXX we should express this using the Splitter config.
1229+-- We can get splitSuffixBy' by appending the suffix to the output segments
1230+-- produced by splitSuffixBy. However, it may add an additional suffix if the last
1231+-- fragment did not have a suffix in the first place.
1233+-- | Like 'splitSuffixBy' but keeps the suffix in the splits.
1235+-- > splitSuffixBy'_ p xs = S.toList $ FL.splitSuffixBy' p (FL.toList) (S.fromList xs)
1237+-- >>> splitSuffixBy'_ (== '.') ""
1240+-- >>> splitSuffixBy'_ (== '.') "."
1243+-- >>> splitSuffixBy'_ (== '.') "a"
1246+-- >>> splitSuffixBy'_ (== '.') ".a"
1249+-- >>> splitSuffixBy'_ (== '.') "a."
1252+-- >>> splitSuffixBy'_ (== '.') "a.b"
1255+-- >>> splitSuffixBy'_ (== '.') "a.b."
1258+-- >>> splitSuffixBy'_ (== '.') "a..b.."
1259+-- > ["a.",".","b.","."]
1262+{-# INLINE _splitSuffixBy' #-}
1264+ :: (IsStream t, Monad m)
1265+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1266+_splitSuffixBy' predicate f m = grouped f (S.map (\a -> (a, predicate a)) m)
1268+------------------------------------------------------------------------------
1269+-- Split on a delimiter
1270+------------------------------------------------------------------------------
1272+-- Int list examples for splitOn:
1274+-- >>> splitList [] [1,2,3,3,4]
1275+-- > [[1],[2],[3],[3],[4]]
1277+-- >>> splitList [5] [1,2,3,3,4]
1280+-- >>> splitList [1] [1,2,3,3,4]
1283+-- >>> splitList [4] [1,2,3,3,4]
1286+-- >>> splitList [2] [1,2,3,3,4]
1289+-- >>> splitList [3] [1,2,3,3,4]
1292+-- >>> splitList [3,3] [1,2,3,3,4]
1295+-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
1298+-- | Split the stream on both sides of a separator sequence, dropping the
1301+-- For illustration, let's define a function that operates on pure lists:
1304+-- splitOn_ pat xs = S.toList $ FL.splitOn (A.fromList pat) (FL.toList) (S.fromList xs)
1307+-- >>> splitOn_ "" "hello"
1308+-- > ["h","e","l","l","o"]
1310+-- >>> splitOn_ "hello" ""
1313+-- >>> splitOn_ "hello" "hello"
1316+-- >>> splitOn_ "x" "hello"
1319+-- >>> splitOn_ "h" "hello"
1322+-- >>> splitOn_ "o" "hello"
1325+-- >>> splitOn_ "e" "hello"
1328+-- >>> splitOn_ "l" "hello"
1331+-- >>> splitOn_ "ll" "hello"
1334+-- 'splitOn' is an inverse of 'intercalate'. The following law always holds:
1336+-- > intercalate . splitOn == id
1338+-- The following law holds when the separator is non-empty and contains none of
1339+-- the elements present in the input lists:
1341+-- > splitOn . intercalate == id
1343+-- The following law always holds:
1345+-- > concat . splitOn . intercalate == concat
1348+{-# INLINE splitOn #-}
1350+ :: (IsStream t, Monad m, Storable a, Enum a, Eq a)
1351+ => Array a -> Fold m a b -> t m a -> t m b
1352+splitOn patt f m = D.fromStreamD $ D.splitOn patt f (D.toStreamD m)
1355+-- This can be implemented easily using Rabin Karp
1356+-- | Split on any one of the given patterns.
1357+{-# INLINE splitOnAny #-}
1359+ :: (IsStream t, Monad m, Storable a, Integral a)
1360+ => [Array a] -> Fold m a b -> t m a -> t m b
1361+splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
1364+-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
1365+-- of a predicate for a single element.
1367+-- > splitSuffixOn_ pat xs = S.toList $ FL.splitSuffixOn (A.fromList pat) (FL.toList) (S.fromList xs)
1369+-- >>> splitSuffixOn_ "." ""
1372+-- >>> splitSuffixOn_ "." "."
1375+-- >>> splitSuffixOn_ "." "a"
1378+-- >>> splitSuffixOn_ "." ".a"
1381+-- >>> splitSuffixOn_ "." "a."
1384+-- >>> splitSuffixOn_ "." "a.b"
1387+-- >>> splitSuffixOn_ "." "a.b."
1390+-- >>> splitSuffixOn_ "." "a..b.."
1391+-- > ["a","","b",""]
1393+-- > lines = splitSuffixOn "\n"
1396+{-# INLINE splitSuffixOn #-}
1398+ :: (IsStream t, Monad m, Storable a, Enum a, Eq a)
1399+ => Array a -> Fold m a b -> t m a -> t m b
1400+splitSuffixOn patt f m =
1401+ D.fromStreamD $ D.splitSuffixOn False patt f (D.toStreamD m)
1404+-- | Like 'splitOn' but drops any empty splits.
1406+{-# INLINE wordsOn #-}
1408+ :: (IsStream t, Monad m, Storable a, Eq a)
1409+ => Array a -> Fold m a b -> t m a -> t m b
1410+wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStreamD m)
1413+-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
1415+-- | Like 'splitOn' but splits the separator as well, as an infix token.
1417+-- > splitOn'_ pat xs = S.toList $ FL.splitOn' (A.fromList pat) (FL.toList) (S.fromList xs)
1419+-- >>> splitOn'_ "" "hello"
1420+-- > ["h","","e","","l","","l","","o"]
1422+-- >>> splitOn'_ "hello" ""
1425+-- >>> splitOn'_ "hello" "hello"
1426+-- > ["","hello",""]
1428+-- >>> splitOn'_ "x" "hello"
1431+-- >>> splitOn'_ "h" "hello"
1432+-- > ["","h","ello"]
1434+-- >>> splitOn'_ "o" "hello"
1435+-- > ["hell","o",""]
1437+-- >>> splitOn'_ "e" "hello"
1438+-- > ["h","e","llo"]
1440+-- >>> splitOn'_ "l" "hello"
1441+-- > ["he","l","","l","o"]
1443+-- >>> splitOn'_ "ll" "hello"
1444+-- > ["he","ll","o"]
1447+{-# INLINE splitOn' #-}
1449+ :: (IsStream t, MonadAsync m, Storable a, Enum a, Eq a)
1450+ => Array a -> Fold m a b -> t m a -> t m b
1451+splitOn' patt f m = S.intersperseM
1452+ (foldl' f (A.toStream patt)) $ splitOn patt f m
1454+-- | Like 'splitSuffixOn' but keeps the suffix intact in the splits.
1456+-- > splitSuffixOn'_ pat xs = S.toList $ FL.splitSuffixOn' (A.fromList pat) (FL.toList) (S.fromList xs)
1458+-- >>> splitSuffixOn'_ "." ""
1461+-- >>> splitSuffixOn'_ "." "."
1464+-- >>> splitSuffixOn'_ "." "a"
1467+-- >>> splitSuffixOn'_ "." ".a"
1470+-- >>> splitSuffixOn'_ "." "a."
1473+-- >>> splitSuffixOn'_ "." "a.b"
1476+-- >>> splitSuffixOn'_ "." "a.b."
1479+-- >>> splitSuffixOn'_ "." "a..b.."
1480+-- > ["a.",".","b.","."]
1483+{-# INLINE splitSuffixOn' #-}
1485+ :: (IsStream t, Monad m, Storable a, Enum a, Eq a)
1486+ => Array a -> Fold m a b -> t m a -> t m b
1487+splitSuffixOn' patt f m =
1488+ D.fromStreamD $ D.splitSuffixOn True patt f (D.toStreamD m)
1491+-- This can be implemented easily using Rabin Karp
1492+-- | Split post any one of the given patterns.
1493+{-# INLINE splitSuffixOnAny #-}
1495+ :: (IsStream t, Monad m, Storable a, Integral a)
1496+ => [Array a] -> Fold m a b -> t m a -> t m b
1497+splitSuffixOnAny subseq f m = undefined
1498+ -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
1501+------------------------------------------------------------------------------
1503+------------------------------------------------------------------------------
1506+-- Buffer until the next element in sequence arrives. The function argument
1507+-- determines the difference in sequence numbers. This could be useful in
1508+-- implementing sequenced streams, for example, TCP reassembly.
1509+{-# INLINE foldOrderedBy #-}
1511+ :: (IsStream t, Monad m)
1512+ => (forall n. Monad n => Fold n a b)
1516+foldOrderedBy = undefined
1519+------------------------------------------------------------------------------
1521+------------------------------------------------------------------------------
1523+-- | Distribute one copy of the stream to each fold and zip the results.
1526+-- |-------Fold m a b--------|
1527+-- ---stream m a---| |---m (b,c)
1528+-- |-------Fold m a c--------|
1530+-- >>> FL.foldl' (FL.tee FL.sum FL.length) (S.enumerateFromTo 1.0 100.0)
1535+tee :: Monad m => Fold m a b -> Fold m a c -> Fold m a (b,c)
1536+tee f1 f2 = (,) <$> f1 <*> f2
1538+{-# INLINE foldNil #-}
1539+foldNil :: Monad m => Fold m a [b]
1540+foldNil = Fold step begin done where
1542+ step _ _ = return []
1545+{-# INLINE foldCons #-}
1546+foldCons :: Monad m => Fold m a b -> Fold m a [b] -> Fold m a [b]
1547+foldCons (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1548+ Fold step begin done
1552+ begin = Tuple' <$> beginL <*> beginR
1553+ step (Tuple' xL xR) a = Tuple' <$> stepL xL a <*> stepR xR a
1554+ done (Tuple' xL xR) = (:) <$> (doneL xL) <*> (doneR xR)
1556+-- XXX use "List" instead of "[]"?, use Array for output to scale it to a large
1557+-- number of consumers?
1559+-- | Distribute one copy of the stream to each fold and collect the results in
1564+-- |-------Fold m a b--------|
1565+-- ---stream m a---| |---m [b]
1566+-- |-------Fold m a b--------|
1571+-- >>> FL.foldl' (FL.distribute [FL.sum, FL.length]) (S.enumerateFromTo 1 5)
1574+-- This is the consumer side dual of the producer side 'sequence' operation.
1577+{-# INLINE distribute #-}
1578+distribute :: Monad m => [Fold m a b] -> Fold m a [b]
1579+distribute [] = foldNil
1580+distribute (x:xs) = foldCons x (distribute xs)
1582+------------------------------------------------------------------------------
1584+------------------------------------------------------------------------------
1586+-- | Partition the input over two folds using an 'Either' partitioning
1591+-- |-------Fold b x--------|
1592+-- -----stream m a --> (Either b c)----| |----(x,y)
1593+-- |-------Fold c y--------|
1596+-- Send input to either fold randomly:
1598+-- >>> import System.Random (randomIO)
1599+-- >>> randomly a = randomIO >>= \x -> return $ if x then Left a else Right a
1600+-- >>> FL.foldl' (FL.partitionByM randomly FL.length FL.length) (S.enumerateFromTo 1 100)
1603+-- Send input to the two folds in a proportion of 2:1:
1606+-- import Data.IORef (newIORef, readIORef, writeIORef)
1607+-- proportionately m n = do
1608+-- ref <- newIORef $ cycle $ concat [replicate m Left, replicate n Right]
1609+-- return $ \\a -> do
1610+-- r <- readIORef ref
1611+-- writeIORef ref $ tail r
1612+-- return $ head r a
1615+-- f <- proportionately 2 1
1616+-- r <- FL.foldl' (FL.partitionByM f FL.length FL.length) (S.enumerateFromTo (1 :: Int) 100)
1623+-- This is the consumer side dual of the producer side 'mergeBy' operation.
1626+{-# INLINE partitionByM #-}
1627+partitionByM :: Monad m
1628+ => (a -> m (Either b c)) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1629+partitionByM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1631+ Fold step begin done
1635+ begin = Tuple' <$> beginL <*> beginR
1636+ step (Tuple' xL xR) a = do
1639+ Left b -> Tuple' <$> stepL xL b <*> return xR
1640+ Right c -> Tuple' <$> return xL <*> stepR xR c
1641+ done (Tuple' xL xR) = (,) <$> doneL xL <*> doneR xR
1643+-- Note: we could use (a -> Bool) instead of (a -> Either b c), but the latter
1644+-- makes the signature clearer as to which case belongs to which fold.
1645+-- XXX need to check the performance in both cases.
1647+-- | Same as 'partitionByM' but with a pure partition function.
1649+-- Count even and odd numbers in a stream:
1652+-- >>> let f = FL.partitionBy (\\n -> if even n then Left n else Right n)
1653+-- (fmap (("Even " ++) . show) FL.length)
1654+-- (fmap (("Odd " ++) . show) FL.length)
1655+-- in FL.foldl' f (S.enumerateFromTo 1 100)
1656+-- ("Even 50","Odd 50")
1660+{-# INLINE partitionBy #-}
1661+partitionBy :: Monad m
1662+ => (a -> Either b c) -> Fold m b x -> Fold m c y -> Fold m a (x, y)
1663+partitionBy f = partitionByM (return . f)
1666+-- | Send one item to each fold in a round-robin fashion. This is the consumer
1667+-- side dual of producer side 'mergeN' operation.
1669+-- partitionN :: Monad m => [Fold m a b] -> Fold m a [b]
1670+-- partitionN fs = Fold step begin done
1672+-- | Demultiplex an input element into a number of typed variants. We want to
1673+-- statically restrict the target values within a set of predefined types, an
1674+-- enumeration of a GADT. We also want to make sure that the Map contains only
1675+-- those types and the full set of those types. Instead of Map it should
1676+-- probably be a lookup-table using an array and not in GC memory.
1678+-- This is the consumer side dual of the producer side 'mux' operation.
1680+-- demux :: (Monad m, Ord k)
1681+-- => (a -> k) -> Map k (Fold m a b) -> Fold m a (Map k b)
1682+-- demux f kv = Fold step begin done
1685+------------------------------------------------------------------------------
1687+------------------------------------------------------------------------------
1689+-- | Like 'unzipWith' but with a monadic splitter function.
1692+{-# INLINE unzipWithM #-}
1693+unzipWithM :: Monad m
1694+ => (a -> m (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
1695+unzipWithM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1696+ Fold step begin done
1700+ step (Tuple' xL xR) a = do
1702+ Tuple' <$> stepL xL b <*> stepR xR c
1703+ begin = Tuple' <$> beginL <*> beginR
1704+ done (Tuple' xL xR) = (,) <$> doneL xL <*> doneR xR
1706+-- | Split elements in the input stream into two parts using a pure splitter
1707+-- function, direct each part to a different fold and zip the results.
1710+{-# INLINE unzipWith #-}
1711+unzipWith :: Monad m
1712+ => (a -> (b,c)) -> Fold m b x -> Fold m c y -> Fold m a (x,y)
1713+unzipWith f = unzipWithM (return . f)
1715+-- | Send the elements of tuples in a stream of tuples through two different
1720+-- |-------Fold a x--------|
1721+-- -----Stream m x----(a,b)--| |----m (x,y)
1722+-- |-------Fold b y--------|
1726+-- This is the consumer side dual of the producer side 'zip' operation.
1729+unzip :: Monad m => Fold m a x -> Fold m b y -> Fold m (a,b) (x,y)
1730+unzip = unzipWith id
1732+------------------------------------------------------------------------------
1734+------------------------------------------------------------------------------
1736+-- | Modify the fold such that when the fold is done, instead of returning the
1737+-- accumulator, it returns a fold. The returned fold starts from where we left
1738+-- i.e. it uses the last accumulator value as the initial value of the
1739+-- accumulator. Thus we can resume the fold later and feed it more input.
1742+-- > more <- FL.foldl (FL.duplicate FL.sum) (S.enumerateFromTo 1 10)
1743+-- > evenMore <- FL.foldl (FL.duplicate more) (S.enumerateFromTo 11 20)
1744+-- > FL.foldl evenMore (S.enumerateFromTo 21 30)
1748+{-# INLINABLE duplicate #-}
1749+duplicate :: Applicative m => Fold m a b -> Fold m a (Fold m a b)
1750+duplicate (Fold step begin done) =
1751+ Fold step begin (\x -> pure (Fold step (pure x) done))
1754+-- All the stream flattening transformations can also be applied to a fold
1757+-- | This can be used to apply all the stream generation operations on folds.
1758+lconcatMap ::(IsStream t, Monad m) => (a -> t m b)
1761+lconcatMap s f1 f2 = undefined
1763+-- All the grouping transformation that we apply to a stream can also be
1764+-- applied to a fold input stream.
1766+-- | Group the input elements of a fold input stream by some criterion and fold
1767+-- each group using a given fold before its fed to the fold.
1769+-- For example, we can copy and distribute a stream to multiple folds and then
1770+-- in each fold we can group the input differently e.g. by one second, one
1771+-- minute and one hour windows respectively and fold each resulting stream of
1776+-- -----Fold m a b----|-Fold n a c-|-Fold n a c-|-...-|----Fold m a c
1779+lgroupsOf :: Int -> Fold m a b -> Fold m b c -> Fold m a c
1780+lgroupsOf n f1 f2 = undefined