@@ -0,0 +1,1781 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE RankNTypes #-}
5+{-# LANGUAGE RecordWildCards #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
7+
8+-- |
9+-- Module : Streamly.Fold
10+-- Copyright : (c) 2019 Composewell Technologies
11+-- (c) 2013 Gabriel Gonzalez
12+-- License : BSD3
13+-- Maintainer : harendra.kumar@gmail.com
14+-- Stability : experimental
15+-- Portability : GHC
16+--
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.
22+--
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.
29+--
30+-- > import qualified Streamly.Fold as FL
31+--
32+--
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.
36+--
37+-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
38+-- 5050
39+
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
43+
44+module Streamly.Fold
45+ (
46+ -- * Fold Type
47+ Fold -- (..)
48+
49+ -- * Folding
50+ -- $termination
51+
52+ , foldl'
53+
54+ -- , tail
55+ -- , init
56+
57+ -- ** Full Folds
58+ , drain
59+ , last
60+ , length
61+ , sum
62+ , product
63+ , maximumBy
64+ , maximum
65+ , minimumBy
66+ , minimum
67+ -- , the
68+ , mean
69+ , variance
70+ , stdDev
71+
72+ -- ** Full Folds (Monoidal)
73+ , mconcat
74+ , foldMap
75+ , foldMapM
76+
77+ -- ** Full Folds (To Containers)
78+ -- , toStream -- experimental
79+ , toStreamRev -- experimental
80+
81+ -- , toList
82+ , toListRev -- experimental
83+
84+ -- ** Partial Folds
85+ -- , drainN
86+ -- , drainWhile
87+ -- , (!!)
88+ -- , genericIndex
89+ , index
90+ , head
91+ -- , findM
92+ , find
93+ , lookup
94+ , findIndex
95+ , elemIndex
96+ , null
97+ , elem
98+ , notElem
99+ -- XXX these are slower than right folds even when full input is used
100+ , all
101+ , any
102+ , and
103+ , or
104+
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:
111+ --
112+ -- >>> FL.foldl' (fmap show FL.sum) (S.enumerateFromTo 1 100)
113+ -- "5050"
114+ --
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.
122+
123+ -- ** Mapping
124+ , lmap
125+ --, sequence
126+ , lmapM
127+
128+ -- ** Scanning
129+ , scanl'
130+ , postscanl'
131+
132+ -- , lscanl'
133+ -- , lscanlM'
134+ -- , lscanl1'
135+ -- , lscanl1M'
136+ --
137+ -- , lpostscanl'
138+ -- , lpostscanlM'
139+ -- , lprescanl'
140+ -- , lprescanlM'
141+
142+ -- ** Filtering
143+ , lfilter
144+ , lfilterM
145+ , ltake
146+ , ltakeWhile
147+ {-
148+ , ltakeWhileM
149+ , ldrop
150+ , ldropWhile
151+ , ldropWhileM
152+ , ldeleteBy
153+ , luniq
154+
155+ -- ** Mapping Filters
156+ , lmapMaybe
157+ , lmapMaybeM
158+
159+ -- ** Scanning Filters
160+ , lfindIndices
161+ , lelemIndices
162+
163+ -- ** Insertion
164+ -- | Insertion adds more elements to the stream.
165+
166+ , linsertBy
167+ , lintersperseM
168+
169+ -- ** Reordering
170+ , lreverse
171+ -}
172+
173+ -- * Stream Splitting Operations
174+ {-
175+ -- ** Spanning
176+ -- | Spanning splits the input into two groups and applies two different
177+ -- folds on each group.
178+
179+ -- Element unaware spanning
180+ -- , splitAt
181+
182+ -- Element aware spanning
183+ , span
184+ , break
185+ , spanBy
186+ , spanRollingBy
187+ , spanned
188+ -}
189+
190+ -- ** Grouping
191+ -- | Grouping splits the stream into groups and applies the supplied fold
192+ -- on each group.
193+
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
197+ -- output stream.
198+ --
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.
206+
207+ -- Element unaware grouping
208+ , groupsOf
209+
210+ -- Element aware grouping
211+ , groups
212+ , groupsBy
213+ -- , groupsRollingBy
214+ , grouped -- XXX experimental
215+
216+ -- ** Splitting by an Element
217+ , splitBy
218+ , splitSuffixBy
219+ -- , splitPrefixBy
220+ , wordsBy
221+
222+ -- ** Splitting on a Sequence
223+ , splitOn
224+ , splitSuffixOn
225+ -- , splitPrefixOn
226+ -- , wordsOn
227+
228+ -- Keeping the delimiters
229+ , splitOn'
230+ , splitSuffixOn'
231+ -- , splitPrefixOn'
232+
233+ -- Splitting by multiple sequences
234+ -- , splitOnAny
235+ -- , splitSuffixOnAny
236+ -- , splitPrefixOnAny
237+
238+ -- ** Distributing
239+ -- |
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.
242+ --
243+ -- @
244+ --
245+ -- |-------Fold m a b--------|
246+ -- ---stream m a---| |---m (b,c,...)
247+ -- |-------Fold m a c--------|
248+ -- | |
249+ -- ...
250+ -- @
251+ --
252+ -- To compute the average of numbers in a stream without going throught he
253+ -- stream twice:
254+ --
255+ -- >>> let avg = (/) <$> FL.sum <*> fmap fromIntegral FL.length
256+ -- >>> FL.foldl' avg (S.enumerateFromTo 1.0 100.0)
257+ -- 50.5
258+ --
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:
262+ --
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})
266+ --
267+ -- The 'Num', 'Floating', and 'Fractional' instances work in the same way.
268+
269+ , tee
270+ , distribute
271+
272+ -- ** Partitioning
273+ -- |
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.
276+ , partitionByM
277+ , partitionBy
278+
279+ -- ** Unzipping
280+ , unzip
281+ , unzipWith
282+ , unzipWithM
283+
284+ -- ** Nested Folds
285+ -- , concatMap
286+ -- , groupsOf
287+ , duplicate -- experimental
288+
289+ {-
290+ -- * Splitter scans
291+ -- | Scans that can be used to split and fold a stream using 'grouped'.
292+ , _newline
293+ -}
294+ )
295+where
296+
297+import Data.Functor.Identity (Identity)
298+import Foreign.Storable (Storable(..))
299+import Prelude
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)
306+
307+import Streamly.Array (Array)
308+import Streamly.Fold.Types (Fold(..))
309+import Streamly.Streams.Serial (SerialT)
310+import Streamly.Streams.StreamK (IsStream())
311+
312+import Streamly.Strict
313+
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
320+
321+-- $termination
322+--
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,
326+--
327+-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
328+-- 5050
329+-- >>> S.sum (S.enumerateFromTo 1 100)
330+-- 5050
331+--
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.
340+--
341+-- >>> S.head (1 `S.cons` undefined)
342+-- Just 1
343+-- >>> FL.foldl' FL.head (1 `S.cons` undefined)
344+-- *** Exception: Prelude.undefined
345+--
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,
348+--
349+-- >>> S.toList $ S.take 1 $ FL.scanl' FL.head (1 `S.cons` undefined)
350+-- [Nothing]
351+--
352+-- The following example extracts the input stream up to a point where the
353+-- running average of elements is no more than 10:
354+--
355+-- @
356+-- > S.toList
357+-- $ S.map (fromJust . fst)
358+-- $ S.takeWhile (\\(_,x) -> x <= 10)
359+-- $ FL.postscanl' ((,) \<$> FL.last \<*> avg) (S.enumerateFromTo 1.0 100.0)
360+-- @
361+-- @
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]
363+-- @
364+
365+------------------------------------------------------------------------------
366+-- Running a Fold
367+------------------------------------------------------------------------------
368+
369+-- | Fold a stream using the supplied monadic fold.
370+--
371+-- >>> FL.foldl' FL.sum (S.enumerateFromTo 1 100)
372+-- 5050
373+--
374+-- @since 0.7.0
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
378+
379+------------------------------------------------------------------------------
380+-- Transformations on fold inputs
381+------------------------------------------------------------------------------
382+
383+-- | @(lmap f fold)@ maps the function @f@ on the input of the fold.
384+--
385+-- >>> FL.foldl' (FL.lmap (\x -> x * x) FL.sum) (S.enumerateFromTo 1 100)
386+-- 338350
387+--
388+-- @since 0.7.0
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
392+ where
393+ step' x a = step x (f a)
394+
395+-- | @(lmapM f fold)@ maps the monadic function @f@ on the input of the fold.
396+--
397+-- @since 0.7.0
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
401+ where
402+ step' x a = f a >>= step x
403+
404+------------------------------------------------------------------------------
405+-- Utilities
406+------------------------------------------------------------------------------
407+
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
415+ where
416+ step_ mx a = return $ Just' $
417+ case mx of
418+ Nothing' -> a
419+ Just' x -> step x a
420+
421+------------------------------------------------------------------------------
422+-- Left folds
423+------------------------------------------------------------------------------
424+
425+------------------------------------------------------------------------------
426+-- Run Effects
427+------------------------------------------------------------------------------
428+
429+-- | A fold that drains all its input, running the effects and discarding the
430+-- results.
431+--
432+-- @since 0.7.0
433+{-# INLINABLE drain #-}
434+drain :: Monad m => Fold m a ()
435+drain = Fold step begin done
436+ where
437+ begin = return ()
438+ step _ _ = return ()
439+ done = return
440+
441+-- | Extract the last element of the input stream, if any.
442+--
443+-- @since 0.7.0
444+{-# INLINABLE last #-}
445+last :: Monad m => Fold m a (Maybe a)
446+last = _Fold1 (flip const)
447+
448+------------------------------------------------------------------------------
449+-- To Summary
450+------------------------------------------------------------------------------
451+
452+-- | Like 'length', except with a more general 'Num' return value
453+--
454+-- @since 0.7.0
455+{-# INLINABLE genericLength #-}
456+genericLength :: (Monad m, Num b) => Fold m a b
457+genericLength = Fold (\n _ -> return $ n + 1) (return 0) return
458+
459+-- | Determine the length of the input stream.
460+--
461+-- @since 0.7.0
462+{-# INLINABLE length #-}
463+length :: Monad m => Fold m a Int
464+length = genericLength
465+
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.
469+--
470+-- @since 0.7.0
471+{-# INLINABLE sum #-}
472+sum :: (Monad m, Num a) => Fold m a a
473+sum = Fold (\x a -> return $ x + a) (return 0) return
474+
475+-- | Determine the product of all elements of a stream of numbers. Returns
476+-- multiplicative identity (@1@) when the stream is empty.
477+--
478+-- @since 0.7.0
479+{-# INLINABLE product #-}
480+product :: (Monad m, Num a) => Fold m a a
481+product = Fold (\x a -> return $ x * a) (return 1) return
482+
483+------------------------------------------------------------------------------
484+-- To Summary (Maybe)
485+------------------------------------------------------------------------------
486+
487+-- | Determine the maximum element in a stream using the supplied comparison
488+-- function.
489+--
490+-- @since 0.7.0
491+{-# INLINABLE maximumBy #-}
492+maximumBy :: Monad m => (a -> a -> Ordering) -> Fold m a (Maybe a)
493+maximumBy cmp = _Fold1 max'
494+ where
495+ max' x y = case cmp x y of
496+ GT -> x
497+ _ -> y
498+
499+-- |
500+-- @
501+-- maximum = 'maximumBy' compare
502+-- @
503+--
504+-- Determine the maximum element in a stream.
505+--
506+-- @since 0.7.0
507+{-# INLINABLE maximum #-}
508+maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
509+maximum = _Fold1 max
510+
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'
515+ where
516+ min' x y = case cmp x y of
517+ GT -> y
518+ _ -> x
519+
520+-- | Determine the minimum element in a stream using the supplied comparison
521+-- function.
522+--
523+-- @since 0.7.0
524+{-# INLINABLE minimum #-}
525+minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
526+minimum = _Fold1 min
527+
528+------------------------------------------------------------------------------
529+-- To Summary (Statistical)
530+------------------------------------------------------------------------------
531+
532+-- | Compute a numerically stable arithmetic mean of all elements in the input
533+-- stream.
534+--
535+-- @since 0.7.0
536+{-# INLINABLE mean #-}
537+mean :: (Monad m, Fractional a) => Fold m a a
538+mean = Fold step (return begin) (return . done)
539+ where
540+ begin = Tuple' 0 0
541+ step (Tuple' x n) y = return $
542+ let n' = n + 1
543+ in Tuple' (x + (y - x) / n') n'
544+ done (Tuple' x _) = x
545+
546+-- | Compute a numerically stable (population) variance over all elements in
547+-- the input stream.
548+--
549+-- @since 0.7.0
550+{-# INLINABLE variance #-}
551+variance :: (Monad m, Fractional a) => Fold m a a
552+variance = Fold step (return begin) (return . done)
553+ where
554+ begin = Tuple3' 0 0 0
555+
556+ step (Tuple3' n mean_ m2) x = return $ Tuple3' n' mean' m2'
557+ where
558+ n' = n + 1
559+ mean' = (n * mean_ + x) / (n + 1)
560+ delta = x - mean_
561+ m2' = m2 + delta * delta * n / (n + 1)
562+
563+ done (Tuple3' n _ m2) = m2 / n
564+
565+-- | Compute a numerically stable (population) standard deviation over all
566+-- elements in the input stream.
567+--
568+-- @since 0.7.0
569+{-# INLINABLE stdDev #-}
570+stdDev :: (Monad m, Floating a) => Fold m a a
571+stdDev = sqrt variance
572+
573+------------------------------------------------------------------------------
574+-- Monoidal left folds
575+------------------------------------------------------------------------------
576+
577+-- | Fold an input stream consisting of monoidal elements using 'mappend'
578+-- and 'mempty'.
579+--
580+-- > FL.foldl FL.mconcat (S.map Sum $ S.enumerateFromTo 1 10)
581+--
582+-- @since 0.7.0
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
586+
587+-- |
588+-- > foldMap f = map f mconcat
589+--
590+-- Make a fold from a pure function that folds the output of the function
591+-- using 'mappend' and 'mempty'.
592+--
593+-- > FL.foldl (FL.foldMap Sum) $ S.enumerateFromTo 1 10
594+--
595+-- @since 0.7.0
596+{-# INLINABLE foldMap #-}
597+foldMap :: (Monad m, Monoid b) => (a -> b) -> Fold m a b
598+foldMap f = lmap f mconcat
599+
600+-- |
601+-- > foldMapM f = mapM f mconcat
602+--
603+-- Make a fold from a monadic function that folds the output of the function
604+-- using 'mappend' and 'mempty'.
605+--
606+-- > FL.foldM (FL.foldMapM (return . Sum)) $ S.enumerateFromTo 1 10
607+--
608+-- @since 0.7.0
609+{-# INLINABLE foldMapM #-}
610+foldMapM :: (Monad m, Monoid b) => (a -> m b) -> Fold m a b
611+foldMapM act = Fold step begin done
612+ where
613+ done = return
614+ begin = return mempty
615+ step m a = do
616+ m' <- act a
617+ return $! mappend m m'
618+
619+------------------------------------------------------------------------------
620+-- To Containers
621+------------------------------------------------------------------------------
622+
623+-- | Folds the input stream to a list.
624+--
625+-- /Warning!/ working on large lists accumulated as buffers in memory could be
626+-- very inefficient, consider using "Streamly.Array" instead.
627+--
628+-- @since 0.7.0
629+
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 :))
634+ (return id)
635+ (return . ($ []))
636+
637+-- This is more efficient than 'toList'. toList is exactly the same as
638+-- reversing the list after toListRev.
639+--
640+-- | Buffers the input stream to a list in the reverse order of the input.
641+--
642+-- /Warning!/ working on large lists accumulated as buffers in memory could be
643+-- very inefficient, consider using "Streamly.Array" instead.
644+--
645+-- @since 0.7.0
646+
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
651+
652+-- | A fold that buffers its input to a pure stream.
653+--
654+-- /Warning!/ working on large streams accumulated as buffers in memory could
655+-- be very inefficient, consider using "Streamly.Array" instead.
656+--
657+-- @since 0.7.0
658+{-# INLINABLE _toStream #-}
659+_toStream :: Monad m => Fold m a (SerialT Identity a)
660+_toStream = Fold (\f x -> return $ f . (x `K.cons`))
661+ (return id)
662+ (return . ($ K.nil))
663+
664+-- This is more efficient than 'toStream'. toStream is exactly the same as
665+-- reversing the stream after toStreamRev.
666+--
667+-- | Buffers the input stream to a pure stream in the reverse order of the
668+-- input.
669+--
670+-- /Warning!/ working on large streams accumulated as buffers in memory could
671+-- be very inefficient, consider using "Streamly.Array" instead.
672+--
673+-- @since 0.7.0
674+
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
679+
680+------------------------------------------------------------------------------
681+-- Partial Folds
682+------------------------------------------------------------------------------
683+
684+------------------------------------------------------------------------------
685+-- To Elements
686+------------------------------------------------------------------------------
687+
688+-- | Like 'index', except with a more general 'Integral' argument
689+--
690+-- @since 0.7.0
691+{-# INLINABLE genericIndex #-}
692+genericIndex :: (Integral i, Monad m) => i -> Fold m a (Maybe a)
693+genericIndex i = Fold step (return $ Left' 0) done
694+ where
695+ step x a = return $
696+ case x of
697+ Left' j -> if i == j
698+ then Right' a
699+ else Left' (j + 1)
700+ _ -> x
701+ done x = return $
702+ case x of
703+ Left' _ -> Nothing
704+ Right' a -> Just a
705+
706+-- | Lookup the element at the given index.
707+--
708+-- @since 0.7.0
709+{-# INLINABLE index #-}
710+index :: Monad m => Int -> Fold m a (Maybe a)
711+index = genericIndex
712+
713+-- | Extract the first element of the stream, if any.
714+--
715+-- @since 0.7.0
716+{-# INLINABLE head #-}
717+head :: Monad m => Fold m a (Maybe a)
718+head = _Fold1 const
719+
720+-- | Returns the first element that satisfies the given predicate.
721+--
722+-- @since 0.7.0
723+{-# INLINABLE find #-}
724+find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
725+find predicate = Fold step (return Nothing') fromStrictMaybe
726+ where
727+ step x a = return $
728+ case x of
729+ Nothing' -> if predicate a
730+ then Just' a
731+ else Nothing'
732+ _ -> x
733+
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@.
736+--
737+-- @since 0.7.0
738+{-# INLINABLE lookup #-}
739+lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
740+lookup a0 = Fold step (return Nothing') fromStrictMaybe
741+ where
742+ step x (a,b) = return $
743+ case x of
744+ Nothing' -> if a == a0
745+ then Just' b
746+ else Nothing'
747+ _ -> x
748+
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
754+
755+-- | Returns the first index that satisfies the given predicate.
756+--
757+-- @since 0.7.0
758+{-# INLINABLE findIndex #-}
759+findIndex :: Monad m => (a -> Bool) -> Fold m a (Maybe Int)
760+findIndex predicate = Fold step (return $ Left' 0) (return . hush)
761+ where
762+ step x a = return $
763+ case x of
764+ Left' i ->
765+ if predicate a
766+ then Right' i
767+ else Left' (i + 1)
768+ _ -> x
769+
770+-- | Returns the first index where a given value is found in the stream.
771+--
772+-- @since 0.7.0
773+{-# INLINABLE elemIndex #-}
774+elemIndex :: (Eq a, Monad m) => a -> Fold m a (Maybe Int)
775+elemIndex a = findIndex (a ==)
776+
777+------------------------------------------------------------------------------
778+-- To Boolean
779+------------------------------------------------------------------------------
780+
781+-- | Return 'True' if the input stream is empty.
782+--
783+-- @since 0.7.0
784+{-# INLINABLE null #-}
785+null :: Monad m => Fold m a Bool
786+null = Fold (\_ _ -> return False) (return True) return
787+
788+-- |
789+-- > any p = lmap p or
790+--
791+-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
792+--
793+-- @since 0.7.0
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
797+
798+-- | Return 'True' if the given element is present in the stream.
799+--
800+-- @since 0.7.0
801+{-# INLINABLE elem #-}
802+elem :: (Eq a, Monad m) => a -> Fold m a Bool
803+elem a = any (a ==)
804+
805+-- |
806+-- > all p = lmap p and
807+--
808+-- | Returns 'True' if all elements of a stream satisfy a predicate.
809+--
810+-- @since 0.7.0
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
814+
815+-- | Returns 'True' if the given element is not present in the stream.
816+--
817+-- @since 0.7.0
818+{-# INLINABLE notElem #-}
819+notElem :: (Eq a, Monad m) => a -> Fold m a Bool
820+notElem a = all (a /=)
821+
822+-- | Returns 'True' if all elements are 'True', 'False' otherwise
823+--
824+-- @since 0.7.0
825+{-# INLINABLE and #-}
826+and :: Monad m => Fold m Bool Bool
827+and = Fold (\x a -> return $ x && a) (return True) return
828+
829+-- | Returns 'True' if any element is 'True', 'False' otherwise
830+--
831+-- @since 0.7.0
832+{-# INLINABLE or #-}
833+or :: Monad m => Fold m Bool Bool
834+or = Fold (\x a -> return $ x || a) (return False) return
835+
836+------------------------------------------------------------------------------
837+-- Scanning with a Fold
838+------------------------------------------------------------------------------
839+
840+-- | Scan a stream using the given monadic fold.
841+--
842+-- @since 0.7.0
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
846+
847+-- | Postscan a stream using the given monadic fold.
848+--
849+-- @since 0.7.0
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
853+
854+-- XXX toPrescanl
855+
856+------------------------------------------------------------------------------
857+-- Filtering
858+------------------------------------------------------------------------------
859+
860+-- | Include only those elements that pass a predicate.
861+--
862+-- >>> FL.foldl (lfilter (> 5) FL.sum) [1..10]
863+-- 40
864+--
865+-- @since 0.7.0
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
869+ where
870+ step' x a = if f a then step x a else return x
871+
872+-- | Like 'lfilter' but with a monadic predicate.
873+--
874+-- @since 0.7.0
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
878+ where
879+ step' x a = do
880+ use <- f a
881+ if use then step x a else return x
882+
883+-- | Take first 'n' elements from the stream and discard the rest.
884+--
885+-- @since 0.7.0
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'
889+ where
890+ initial' = fmap (Tuple' 0) initial
891+ step' (Tuple' i r) a = do
892+ if i < n
893+ then do
894+ res <- step r a
895+ return $ Tuple' (i + 1) res
896+ else return $ Tuple' i r
897+ done' (Tuple' _ r) = done r
898+
899+-- | Takes elements from the input as long as the predicate succeeds.
900+--
901+-- @since 0.7.0
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'
905+ where
906+ initial' = fmap Left' initial
907+ step' (Left' r) a = do
908+ if predicate a
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
914+
915+------------------------------------------------------------------------------
916+-- Grouping/Splitting
917+------------------------------------------------------------------------------
918+
919+------------------------------------------------------------------------------
920+-- Grouping without looking at elements
921+------------------------------------------------------------------------------
922+--
923+------------------------------------------------------------------------------
924+-- Binary APIs
925+------------------------------------------------------------------------------
926+--
927+
928+{-
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
932+-- stream.
933+--
934+splitAt
935+ :: Monad m
936+ => Int
937+ -> Fold m a b
938+ -> Fold m a c
939+ -> Fold m a (b, c)
940+splitAt n = undefined
941+-}
942+
943+------------------------------------------------------------------------------
944+-- N-ary APIs
945+------------------------------------------------------------------------------
946+
947+-- | Group the input stream into groups of @n@ elements each and then fold each
948+-- group using the provided fold function.
949+--
950+-- >> S.toList $ FL.groupsOf 2 FL.sum (S.enumerateFromTo 1 10)
951+-- > [3,7,11,15,19]
952+--
953+-- @since 0.7.0
954+{-# INLINE groupsOf #-}
955+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)
959+
960+------------------------------------------------------------------------------
961+-- Element Aware APIs
962+------------------------------------------------------------------------------
963+--
964+------------------------------------------------------------------------------
965+-- Binary APIs
966+------------------------------------------------------------------------------
967+
968+{-
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
971+-- of the input.
972+--
973+-- This is the most general spanning combinator, all others can be implemented
974+-- in terms of this.
975+--
976+spanned
977+ :: Monad m
978+ => Fold m a b
979+ -> Fold m a c
980+ -> Fold m (a, Bool) (b, c)
981+spanned f m = undefined
982+
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.
986+spanBy
987+ :: Monad m
988+ => (a -> a -> Bool)
989+ -> Fold m a b
990+ -> Fold m a c
991+ -> Fold m a (b, c)
992+spanBy cmp f1 f2 = undefined
993+
994+-- |
995+-- > span p = spanBy (\_ x -> p x)
996+--
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
999+-- input.
1000+span
1001+ :: Monad m
1002+ => (a -> Bool)
1003+ -> Fold m a b
1004+ -> Fold m a c
1005+ -> Fold m a (b, c)
1006+span p = spanBy (\_ x -> p x)
1007+
1008+-- |
1009+-- > break p = span (not . p)
1010+--
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
1013+-- input.
1014+break
1015+ :: Monad m
1016+ => (a -> Bool)
1017+ -> Fold m a b
1018+ -> Fold m a c
1019+ -> Fold m a (b, c)
1020+break p = span (not . p)
1021+
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.
1024+spanRollingBy
1025+ :: Monad m
1026+ => (a -> a -> Bool)
1027+ -> Fold m a b
1028+ -> Fold m a c
1029+ -> Fold m a (b, c)
1030+spanRollingBy cmp f1 f2 = undefined
1031+-}
1032+
1033+------------------------------------------------------------------------------
1034+-- N-ary APIs
1035+------------------------------------------------------------------------------
1036+--
1037+-- XXX should we use a strict pair?
1038+--
1039+-- | The splitter returns True if the current element is the last element of
1040+-- the group, otherwise returns false.
1041+--
1042+-- @since 0.7.0
1043+{-# INLINE grouped #-}
1044+grouped
1045+ :: (IsStream t, Monad m)
1046+ => Fold m a b
1047+ -> t m (a, Bool)
1048+ -> t m b
1049+grouped f m = D.fromStreamD $ D.grouped f (D.toStreamD m)
1050+
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 ->
1054+ if x == '\n'
1055+ then (x,True) `K.cons` xs
1056+ else (x,False) `K.cons` xs) K.nil m
1057+
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
1061+-- starts.
1062+--
1063+-- >>> S.toList $ FL.groupsBy (==) FL.toList $ S.fromList [1,1,2,2]
1064+-- > [[1,1],[2,2]]
1065+--
1066+-- @since 0.7.0
1067+groupsBy
1068+ :: (IsStream t, Monad m)
1069+ => (a -> a -> Bool)
1070+ -> Fold m a b
1071+ -> t m a
1072+ -> t m b
1073+groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
1074+
1075+{-
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
1080+-- starts.
1081+groupsRollingBy
1082+ :: (IsStream t, Monad m)
1083+ => (a -> a -> Bool)
1084+ -> Fold m a b
1085+ -> t m a
1086+ -> t m b
1087+groupsRollingBy cmp f m = undefined
1088+-}
1089+
1090+-- |
1091+-- > groups = groupsBy (==)
1092+--
1093+-- >>> S.toList $ FL.groups FL.toList $ S.fromList [1,1,2,2]
1094+-- > [[1,1],[2,2]]
1095+--
1096+-- @since 0.7.0
1097+groups :: (IsStream t, Monad m, Eq a) => Fold m a b -> t m a -> t m b
1098+groups = groupsBy (==)
1099+
1100+------------------------------------------------------------------------------
1101+-- Binary splitting on a separator
1102+------------------------------------------------------------------------------
1103+
1104+{-
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
1108+-}
1109+
1110+------------------------------------------------------------------------------
1111+-- N-ary split on a predicate
1112+------------------------------------------------------------------------------
1113+
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
1118+-- as argument.
1119+
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'.
1128+--
1129+-- Let's use the following definition for illustration:
1130+--
1131+-- > splitBy_ p xs = S.toList $ FL.splitBy p (FL.toList) (S.fromList xs)
1132+--
1133+-- >>> splitBy_ (== '.') ""
1134+-- [""]
1135+--
1136+-- >>> splitBy_ (== '.') "."
1137+-- ["",""]
1138+--
1139+-- >>> splitBy_ (== '.') ".a"
1140+-- > ["","a"]
1141+--
1142+-- >>> splitBy_ (== '.') "a."
1143+-- > ["a",""]
1144+--
1145+-- >>> splitBy_ (== '.') "a.b"
1146+-- > ["a","b"]
1147+--
1148+-- >>> splitBy_ (== '.') "a..b"
1149+-- > ["a","","b"]
1150+--
1151+-- @since 0.7.0
1152+{-# INLINE splitBy #-}
1153+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)
1158+
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
1163+-- 'splitBy'.
1164+--
1165+-- > splitSuffixBy_ p xs = S.toList $ FL.splitSuffixBy p (FL.toList) (S.fromList xs)
1166+--
1167+-- >>> splitSuffixBy_ (== '.') ""
1168+-- []
1169+--
1170+-- >>> splitSuffixBy_ (== '.') "."
1171+-- [""]
1172+--
1173+-- >>> splitSuffixBy_ (== '.') "a"
1174+-- ["a"]
1175+--
1176+-- >>> splitSuffixBy_ (== '.') ".a"
1177+-- > ["","a"]
1178+--
1179+-- >>> splitSuffixBy_ (== '.') "a."
1180+-- > ["a"]
1181+--
1182+-- >>> splitSuffixBy_ (== '.') "a.b"
1183+-- > ["a","b"]
1184+--
1185+-- >>> splitSuffixBy_ (== '.') "a.b."
1186+-- > ["a","b"]
1187+--
1188+-- >>> splitSuffixBy_ (== '.') "a..b.."
1189+-- > ["a","","b",""]
1190+--
1191+-- > lines = splitSuffixBy (== '\n')
1192+--
1193+-- @since 0.7.0
1194+{-# INLINE splitSuffixBy #-}
1195+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)
1200+
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.
1205+--
1206+-- > wordsBy' p xs = S.toList $ FL.wordsBy p (FL.toList) (S.fromList xs)
1207+--
1208+-- >>> wordsBy' (== ',') ""
1209+-- > []
1210+--
1211+-- >>> wordsBy' (== ',') ","
1212+-- > []
1213+--
1214+-- >>> wordsBy' (== ',') ",a,,b,"
1215+-- > ["a","b"]
1216+--
1217+-- > words = wordsBy isSpace
1218+--
1219+-- @since 0.7.0
1220+{-# INLINE wordsBy #-}
1221+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)
1226+
1227+-- XXX we should express this using the Splitter config.
1228+--
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.
1232+
1233+-- | Like 'splitSuffixBy' but keeps the suffix in the splits.
1234+--
1235+-- > splitSuffixBy'_ p xs = S.toList $ FL.splitSuffixBy' p (FL.toList) (S.fromList xs)
1236+--
1237+-- >>> splitSuffixBy'_ (== '.') ""
1238+-- []
1239+--
1240+-- >>> splitSuffixBy'_ (== '.') "."
1241+-- ["."]
1242+--
1243+-- >>> splitSuffixBy'_ (== '.') "a"
1244+-- ["a"]
1245+--
1246+-- >>> splitSuffixBy'_ (== '.') ".a"
1247+-- > [".","a"]
1248+--
1249+-- >>> splitSuffixBy'_ (== '.') "a."
1250+-- > ["a."]
1251+--
1252+-- >>> splitSuffixBy'_ (== '.') "a.b"
1253+-- > ["a.","b"]
1254+--
1255+-- >>> splitSuffixBy'_ (== '.') "a.b."
1256+-- > ["a.","b."]
1257+--
1258+-- >>> splitSuffixBy'_ (== '.') "a..b.."
1259+-- > ["a.",".","b.","."]
1260+--
1261+-- @since 0.7.0
1262+{-# INLINE _splitSuffixBy' #-}
1263+_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)
1267+
1268+------------------------------------------------------------------------------
1269+-- Split on a delimiter
1270+------------------------------------------------------------------------------
1271+
1272+-- Int list examples for splitOn:
1273+--
1274+-- >>> splitList [] [1,2,3,3,4]
1275+-- > [[1],[2],[3],[3],[4]]
1276+--
1277+-- >>> splitList [5] [1,2,3,3,4]
1278+-- > [[1,2,3,3,4]]
1279+--
1280+-- >>> splitList [1] [1,2,3,3,4]
1281+-- > [[],[2,3,3,4]]
1282+--
1283+-- >>> splitList [4] [1,2,3,3,4]
1284+-- > [[1,2,3,3],[]]
1285+--
1286+-- >>> splitList [2] [1,2,3,3,4]
1287+-- > [[1],[3,3,4]]
1288+--
1289+-- >>> splitList [3] [1,2,3,3,4]
1290+-- > [[1,2],[],[4]]
1291+--
1292+-- >>> splitList [3,3] [1,2,3,3,4]
1293+-- > [[1,2],[4]]
1294+--
1295+-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
1296+-- > [[],[]]
1297+
1298+-- | Split the stream on both sides of a separator sequence, dropping the
1299+-- separator.
1300+--
1301+-- For illustration, let's define a function that operates on pure lists:
1302+--
1303+-- @
1304+-- splitOn_ pat xs = S.toList $ FL.splitOn (A.fromList pat) (FL.toList) (S.fromList xs)
1305+-- @
1306+--
1307+-- >>> splitOn_ "" "hello"
1308+-- > ["h","e","l","l","o"]
1309+--
1310+-- >>> splitOn_ "hello" ""
1311+-- > [""]
1312+--
1313+-- >>> splitOn_ "hello" "hello"
1314+-- > ["",""]
1315+--
1316+-- >>> splitOn_ "x" "hello"
1317+-- > ["hello"]
1318+--
1319+-- >>> splitOn_ "h" "hello"
1320+-- > ["","ello"]
1321+--
1322+-- >>> splitOn_ "o" "hello"
1323+-- > ["hell",""]
1324+--
1325+-- >>> splitOn_ "e" "hello"
1326+-- > ["h","llo"]
1327+--
1328+-- >>> splitOn_ "l" "hello"
1329+-- > ["he","","o"]
1330+--
1331+-- >>> splitOn_ "ll" "hello"
1332+-- > ["he","o"]
1333+--
1334+-- 'splitOn' is an inverse of 'intercalate'. The following law always holds:
1335+--
1336+-- > intercalate . splitOn == id
1337+--
1338+-- The following law holds when the separator is non-empty and contains none of
1339+-- the elements present in the input lists:
1340+--
1341+-- > splitOn . intercalate == id
1342+--
1343+-- The following law always holds:
1344+--
1345+-- > concat . splitOn . intercalate == concat
1346+--
1347+-- @since 0.7.0
1348+{-# INLINE splitOn #-}
1349+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)
1353+
1354+{-
1355+-- This can be implemented easily using Rabin Karp
1356+-- | Split on any one of the given patterns.
1357+{-# INLINE splitOnAny #-}
1358+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)
1362+-}
1363+
1364+-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
1365+-- of a predicate for a single element.
1366+--
1367+-- > splitSuffixOn_ pat xs = S.toList $ FL.splitSuffixOn (A.fromList pat) (FL.toList) (S.fromList xs)
1368+--
1369+-- >>> splitSuffixOn_ "." ""
1370+-- [""]
1371+--
1372+-- >>> splitSuffixOn_ "." "."
1373+-- [""]
1374+--
1375+-- >>> splitSuffixOn_ "." "a"
1376+-- ["a"]
1377+--
1378+-- >>> splitSuffixOn_ "." ".a"
1379+-- > ["","a"]
1380+--
1381+-- >>> splitSuffixOn_ "." "a."
1382+-- > ["a"]
1383+--
1384+-- >>> splitSuffixOn_ "." "a.b"
1385+-- > ["a","b"]
1386+--
1387+-- >>> splitSuffixOn_ "." "a.b."
1388+-- > ["a","b"]
1389+--
1390+-- >>> splitSuffixOn_ "." "a..b.."
1391+-- > ["a","","b",""]
1392+--
1393+-- > lines = splitSuffixOn "\n"
1394+--
1395+-- @since 0.7.0
1396+{-# INLINE splitSuffixOn #-}
1397+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)
1402+
1403+{-
1404+-- | Like 'splitOn' but drops any empty splits.
1405+--
1406+{-# INLINE wordsOn #-}
1407+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)
1411+-}
1412+
1413+-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
1414+--
1415+-- | Like 'splitOn' but splits the separator as well, as an infix token.
1416+--
1417+-- > splitOn'_ pat xs = S.toList $ FL.splitOn' (A.fromList pat) (FL.toList) (S.fromList xs)
1418+--
1419+-- >>> splitOn'_ "" "hello"
1420+-- > ["h","","e","","l","","l","","o"]
1421+--
1422+-- >>> splitOn'_ "hello" ""
1423+-- > [""]
1424+--
1425+-- >>> splitOn'_ "hello" "hello"
1426+-- > ["","hello",""]
1427+--
1428+-- >>> splitOn'_ "x" "hello"
1429+-- > ["hello"]
1430+--
1431+-- >>> splitOn'_ "h" "hello"
1432+-- > ["","h","ello"]
1433+--
1434+-- >>> splitOn'_ "o" "hello"
1435+-- > ["hell","o",""]
1436+--
1437+-- >>> splitOn'_ "e" "hello"
1438+-- > ["h","e","llo"]
1439+--
1440+-- >>> splitOn'_ "l" "hello"
1441+-- > ["he","l","","l","o"]
1442+--
1443+-- >>> splitOn'_ "ll" "hello"
1444+-- > ["he","ll","o"]
1445+--
1446+-- @since 0.7.0
1447+{-# INLINE splitOn' #-}
1448+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
1453+
1454+-- | Like 'splitSuffixOn' but keeps the suffix intact in the splits.
1455+--
1456+-- > splitSuffixOn'_ pat xs = S.toList $ FL.splitSuffixOn' (A.fromList pat) (FL.toList) (S.fromList xs)
1457+--
1458+-- >>> splitSuffixOn'_ "." ""
1459+-- [""]
1460+--
1461+-- >>> splitSuffixOn'_ "." "."
1462+-- ["."]
1463+--
1464+-- >>> splitSuffixOn'_ "." "a"
1465+-- ["a"]
1466+--
1467+-- >>> splitSuffixOn'_ "." ".a"
1468+-- > [".","a"]
1469+--
1470+-- >>> splitSuffixOn'_ "." "a."
1471+-- > ["a."]
1472+--
1473+-- >>> splitSuffixOn'_ "." "a.b"
1474+-- > ["a.","b"]
1475+--
1476+-- >>> splitSuffixOn'_ "." "a.b."
1477+-- > ["a.","b."]
1478+--
1479+-- >>> splitSuffixOn'_ "." "a..b.."
1480+-- > ["a.",".","b.","."]
1481+--
1482+-- @since 0.7.0
1483+{-# INLINE splitSuffixOn' #-}
1484+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)
1489+
1490+{-
1491+-- This can be implemented easily using Rabin Karp
1492+-- | Split post any one of the given patterns.
1493+{-# INLINE splitSuffixOnAny #-}
1494+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)
1499+-}
1500+
1501+------------------------------------------------------------------------------
1502+-- Grouped by order
1503+------------------------------------------------------------------------------
1504+
1505+{-
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 #-}
1510+foldOrderedBy
1511+ :: (IsStream t, Monad m)
1512+ => (forall n. Monad n => Fold n a b)
1513+ -> (a -> a -> Int)
1514+ -> t m a
1515+ -> t m b
1516+foldOrderedBy = undefined
1517+-}
1518+
1519+------------------------------------------------------------------------------
1520+-- Distributing
1521+------------------------------------------------------------------------------
1522+--
1523+-- | Distribute one copy of the stream to each fold and zip the results.
1524+--
1525+-- @
1526+-- |-------Fold m a b--------|
1527+-- ---stream m a---| |---m (b,c)
1528+-- |-------Fold m a c--------|
1529+-- @
1530+-- >>> FL.foldl' (FL.tee FL.sum FL.length) (S.enumerateFromTo 1.0 100.0)
1531+-- (5050.0,100)
1532+--
1533+-- @since 0.7.0
1534+{-# INLINE tee #-}
1535+tee :: Monad m => Fold m a b -> Fold m a c -> Fold m a (b,c)
1536+tee f1 f2 = (,) <$> f1 <*> f2
1537+
1538+{-# INLINE foldNil #-}
1539+foldNil :: Monad m => Fold m a [b]
1540+foldNil = Fold step begin done where
1541+ begin = return []
1542+ step _ _ = return []
1543+ done = return
1544+
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
1549+
1550+ where
1551+
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)
1555+
1556+-- XXX use "List" instead of "[]"?, use Array for output to scale it to a large
1557+-- number of consumers?
1558+--
1559+-- | Distribute one copy of the stream to each fold and collect the results in
1560+-- a container.
1561+--
1562+-- @
1563+--
1564+-- |-------Fold m a b--------|
1565+-- ---stream m a---| |---m [b]
1566+-- |-------Fold m a b--------|
1567+-- | |
1568+-- ...
1569+-- @
1570+--
1571+-- >>> FL.foldl' (FL.distribute [FL.sum, FL.length]) (S.enumerateFromTo 1 5)
1572+-- [15,5]
1573+--
1574+-- This is the consumer side dual of the producer side 'sequence' operation.
1575+--
1576+-- @since 0.7.0
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)
1581+
1582+------------------------------------------------------------------------------
1583+-- Partitioning
1584+------------------------------------------------------------------------------
1585+--
1586+-- | Partition the input over two folds using an 'Either' partitioning
1587+-- predicate.
1588+--
1589+-- @
1590+--
1591+-- |-------Fold b x--------|
1592+-- -----stream m a --> (Either b c)----| |----(x,y)
1593+-- |-------Fold c y--------|
1594+-- @
1595+--
1596+-- Send input to either fold randomly:
1597+--
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)
1601+-- (59,41)
1602+--
1603+-- Send input to the two folds in a proportion of 2:1:
1604+--
1605+-- @
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
1613+--
1614+-- main = do
1615+-- f <- proportionately 2 1
1616+-- r <- FL.foldl' (FL.partitionByM f FL.length FL.length) (S.enumerateFromTo (1 :: Int) 100)
1617+-- print r
1618+-- @
1619+-- @
1620+-- (67,33)
1621+-- @
1622+--
1623+-- This is the consumer side dual of the producer side 'mergeBy' operation.
1624+--
1625+-- @since 0.7.0
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) =
1630+
1631+ Fold step begin done
1632+
1633+ where
1634+
1635+ begin = Tuple' <$> beginL <*> beginR
1636+ step (Tuple' xL xR) a = do
1637+ r <- f a
1638+ case r of
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
1642+
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.
1646+
1647+-- | Same as 'partitionByM' but with a pure partition function.
1648+--
1649+-- Count even and odd numbers in a stream:
1650+--
1651+-- @
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")
1657+-- @
1658+--
1659+-- @since 0.7.0
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)
1664+
1665+{-
1666+-- | Send one item to each fold in a round-robin fashion. This is the consumer
1667+-- side dual of producer side 'mergeN' operation.
1668+--
1669+-- partitionN :: Monad m => [Fold m a b] -> Fold m a [b]
1670+-- partitionN fs = Fold step begin done
1671+
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.
1677+--
1678+-- This is the consumer side dual of the producer side 'mux' operation.
1679+--
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
1683+-}
1684+
1685+------------------------------------------------------------------------------
1686+-- Unzipping
1687+------------------------------------------------------------------------------
1688+--
1689+-- | Like 'unzipWith' but with a monadic splitter function.
1690+--
1691+-- @since 0.7.0
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
1697+
1698+ where
1699+
1700+ step (Tuple' xL xR) a = do
1701+ (b,c) <- f a
1702+ Tuple' <$> stepL xL b <*> stepR xR c
1703+ begin = Tuple' <$> beginL <*> beginR
1704+ done (Tuple' xL xR) = (,) <$> doneL xL <*> doneR xR
1705+
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.
1708+--
1709+-- @since 0.7.0
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)
1714+
1715+-- | Send the elements of tuples in a stream of tuples through two different
1716+-- folds.
1717+--
1718+-- @
1719+--
1720+-- |-------Fold a x--------|
1721+-- -----Stream m x----(a,b)--| |----m (x,y)
1722+-- |-------Fold b y--------|
1723+--
1724+-- @
1725+--
1726+-- This is the consumer side dual of the producer side 'zip' operation.
1727+--
1728+-- @since 0.7.0
1729+unzip :: Monad m => Fold m a x -> Fold m b y -> Fold m (a,b) (x,y)
1730+unzip = unzipWith id
1731+
1732+------------------------------------------------------------------------------
1733+-- Nesting
1734+------------------------------------------------------------------------------
1735+--
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.
1740+--
1741+-- >> do
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)
1745+-- > 465
1746+--
1747+-- @since 0.7.0
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))
1752+
1753+{-
1754+-- All the stream flattening transformations can also be applied to a fold
1755+-- input stream.
1756+
1757+-- | This can be used to apply all the stream generation operations on folds.
1758+lconcatMap ::(IsStream t, Monad m) => (a -> t m b)
1759+ -> Fold m b c
1760+ -> Fold m a c
1761+lconcatMap s f1 f2 = undefined
1762+
1763+-- All the grouping transformation that we apply to a stream can also be
1764+-- applied to a fold input stream.
1765+
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.
1768+--
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
1772+-- folds.
1773+--
1774+-- @
1775+--
1776+-- -----Fold m a b----|-Fold n a c-|-Fold n a c-|-...-|----Fold m a c
1777+--
1778+-- @
1779+lgroupsOf :: Int -> Fold m a b -> Fold m b c -> Fold m a c
1780+lgroupsOf n f1 f2 = undefined
1781+-}