@@ -60,6 +60,7 @@ module Streamly.Internal.Data.Fold
61 -- ** Full Folds (Monoidal)
61 -- ** Full Folds (Monoidal)
64 , foldMapM
65 , foldMapM
@@ -386,6 +387,8 @@ _Fold1 step = Fold step_ (return Nothing') (return . toMaybe)
386-- | A fold that drains all its input, running the effects and discarding the
387-- | A fold that drains all its input, running the effects and discarding the
387-- results.
388-- results.
390+-- > drain = drainBy (const (return ()))
389-- @since 0.7.0
392-- @since 0.7.0
390{-# INLINABLE drain #-}
393{-# INLINABLE drain #-}
391drain :: Monad m => Fold m a ()
394drain :: Monad m => Fold m a ()
@@ -397,6 +400,7 @@ drain = Fold step begin done
399-- > drainBy f = lmapM f drain
402-- > drainBy f = lmapM f drain
403+-- > drainBy = FL.foldMapM (void . f)
401-- Drain all input after passing it through a monadic function. This is the
405-- Drain all input after passing it through a monadic function. This is the
402-- dual of mapM_ on stream producers.
406-- dual of mapM_ on stream producers.
@@ -412,6 +416,8 @@ drainBy2 f = Fold2 (const (void . f)) (\_ -> return ()) return
413-- | Extract the last element of the input stream, if any.
417-- | Extract the last element of the input stream, if any.
419+-- > last = fmap getLast $ FL.foldMap (Last . Just)
415-- @since 0.7.0
421-- @since 0.7.0
416{-# INLINABLE last #-}
422{-# INLINABLE last #-}
417last :: Monad m => Fold m a (Maybe a)
423last :: Monad m => Fold m a (Maybe a)
@@ -423,6 +429,8 @@ last = _Fold1 (flip const)
424-- | Like 'length', except with a more general 'Num' return value
430-- | Like 'length', except with a more general 'Num' return value
432+-- > genericLength = fmap getSum $ foldMap (Sum . const 1)
426-- @since 0.7.0
434-- @since 0.7.0
427{-# INLINABLE genericLength #-}
435{-# INLINABLE genericLength #-}
428genericLength :: (Monad m, Num b) => Fold m a b
436genericLength :: (Monad m, Num b) => Fold m a b
@@ -430,6 +438,8 @@ genericLength = Fold (\n _ -> return $ n + 1) (return 0) return
431-- | Determine the length of the input stream.
439-- | Determine the length of the input stream.
441+-- > length = fmap getSum $ foldMap (Sum . const 1)
433-- @since 0.7.0
443-- @since 0.7.0
434{-# INLINABLE length #-}
444{-# INLINABLE length #-}
435length :: Monad m => Fold m a Int
445length :: Monad m => Fold m a Int
@@ -439,14 +449,18 @@ length = genericLength
439-- identity (@0@) when the stream is empty. Note that this is not numerically
449-- identity (@0@) when the stream is empty. Note that this is not numerically
440-- stable for floating point numbers.
450-- stable for floating point numbers.
452+-- > sum = fmap getSum $ FL.foldMap Sum
442-- @since 0.7.0
454-- @since 0.7.0
443−{-# INLINABLE sum #-}
455+{-# INLINE sum #-}
444sum :: (Monad m, Num a) => Fold m a a
456sum :: (Monad m, Num a) => Fold m a a
445sum = Fold (\x a -> return $ x + a) (return 0) return
457sum = Fold (\x a -> return $ x + a) (return 0) return
447-- | Determine the product of all elements of a stream of numbers. Returns
459-- | Determine the product of all elements of a stream of numbers. Returns
448-- multiplicative identity (@1@) when the stream is empty.
460-- multiplicative identity (@1@) when the stream is empty.
462+-- > product = fmap getProduct $ FL.foldMap Product
450-- @since 0.7.0
464-- @since 0.7.0
451{-# INLINABLE product #-}
465{-# INLINABLE product #-}
452product :: (Monad m, Num a) => Fold m a a
466product :: (Monad m, Num a) => Fold m a a
@@ -475,6 +489,8 @@ maximumBy cmp = _Fold1 max'
476-- Determine the maximum element in a stream.
490-- Determine the maximum element in a stream.
492+-- Compare with @FL.foldMap Max@.
478-- @since 0.7.0
494-- @since 0.7.0
479{-# INLINABLE maximum #-}
495{-# INLINABLE maximum #-}
480maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
496maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
@@ -494,6 +510,12 @@ minimumBy cmp = _Fold1 min'
494-- | Determine the minimum element in a stream using the supplied comparison
510-- | Determine the minimum element in a stream using the supplied comparison
495-- function.
511-- function.
514+-- minimum = 'minimumBy' compare
517+-- Compare with @FL.foldMap Min@.
497-- @since 0.7.0
519-- @since 0.7.0
498{-# INLINABLE minimum #-}
520{-# INLINABLE minimum #-}
499minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
521minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
@@ -591,18 +613,31 @@ rollingHashFirstN n = ltake n rollingHash
591-- Monoidal left folds
613-- Monoidal left folds
592------------------------------------------------------------------------------
614------------------------------------------------------------------------------
616+-- | 'mappend' the elements of an input stream to a provided starting value.
618+-- > S.fold (FL.mconcatTo 10) (S.map Sum $ S.enumerateFromTo 1 10)
620+-- This could be faster than (fmap (m0 <>) FL.mconcat) especially when we have
621+-- to perform the operation many times.
625+{-# INLINE mconcatTo #-}
626+mconcatTo :: (Monad m, Monoid a) => a -> Fold m a a
627+mconcatTo i = Fold (\x a -> return $ mappend x a) (return i) return
594-- | Fold an input stream consisting of monoidal elements using 'mappend'
629-- | Fold an input stream consisting of monoidal elements using 'mappend'
595-- and 'mempty'.
630-- and 'mempty'.
597-- > S.fold FL.mconcat (S.map Sum $ S.enumerateFromTo 1 10)
632-- > S.fold FL.mconcat (S.map Sum $ S.enumerateFromTo 1 10)
599-- @since 0.7.0
634-- @since 0.7.0
600−{-# INLINABLE mconcat #-}
635+{-# INLINE mconcat #-}
601mconcat :: (Monad m, Monoid a) => Fold m a a
636mconcat :: (Monad m, Monoid a) => Fold m a a
602−mconcat = Fold (\x a -> return $ mappend x a) (return mempty) return
637+mconcat = mconcatTo mempty
605−-- > foldMap f = map f mconcat
640+-- > foldMap f = lmap f mconcat
607-- Make a fold from a pure function that folds the output of the function
642-- Make a fold from a pure function that folds the output of the function
608-- using 'mappend' and 'mempty'.
643-- using 'mappend' and 'mempty'.
@@ -615,7 +650,7 @@ foldMap :: (Monad m, Monoid b) => (a -> b) -> Fold m a b
615foldMap f = lmap f mconcat
650foldMap f = lmap f mconcat
618−-- > foldMapM f = mapM f mconcat
653+-- > foldMapM f = lmapM f mconcat
620-- Make a fold from a monadic function that folds the output of the function
655-- Make a fold from a monadic function that folds the output of the function
621-- using 'mappend' and 'mempty'.
656-- using 'mappend' and 'mempty'.
@@ -698,6 +733,8 @@ index = genericIndex
699-- | Extract the first element of the stream, if any.
734-- | Extract the first element of the stream, if any.
736+-- > head = fmap getFirst $ FL.foldMap (First . Just)
701-- @since 0.7.0
738-- @since 0.7.0
702{-# INLINABLE head #-}
739{-# INLINABLE head #-}
703head :: Monad m => Fold m a (Maybe a)
740head :: Monad m => Fold m a (Maybe a)
@@ -705,6 +742,11 @@ head = _Fold1 const
706-- | Returns the first element that satisfies the given predicate.
743-- | Returns the first element that satisfies the given predicate.
746+-- find p = fmap getFirst $
747+-- foldMap (\x -> First (if p x then Just x else Nothing))
708-- @since 0.7.0
750-- @since 0.7.0
709{-# INLINABLE find #-}
751{-# INLINABLE find #-}
710find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
752find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
@@ -720,6 +762,8 @@ find predicate = Fold step (return Nothing') (return . toMaybe)
720-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
762-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
721-- first pair where the key equals the given value @a@.
763-- first pair where the key equals the given value @a@.
765+-- > lookup = snd <$> find ((==) . fst)
723-- @since 0.7.0
767-- @since 0.7.0
724{-# INLINABLE lookup #-}
768{-# INLINABLE lookup #-}
725lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
769lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
@@ -755,6 +799,8 @@ findIndex predicate = Fold step (return $ Left' 0) (return . hush)
756-- | Returns the first index where a given value is found in the stream.
800-- | Returns the first index where a given value is found in the stream.
802+-- > elemIndex a = findIndex (== a)
758-- @since 0.7.0
804-- @since 0.7.0
759{-# INLINABLE elemIndex #-}
805{-# INLINABLE elemIndex #-}
760elemIndex :: (Eq a, Monad m) => a -> Fold m a (Maybe Int)
806elemIndex :: (Eq a, Monad m) => a -> Fold m a (Maybe Int)
@@ -766,6 +812,8 @@ elemIndex a = findIndex (a ==)
767-- | Return 'True' if the input stream is empty.
813-- | Return 'True' if the input stream is empty.
815+-- > null = fmap isJust head
769-- @since 0.7.0
817-- @since 0.7.0
770{-# INLINABLE null #-}
818{-# INLINABLE null #-}
771null :: Monad m => Fold m a Bool
819null :: Monad m => Fold m a Bool
@@ -773,6 +821,7 @@ null = Fold (\_ _ -> return False) (return True) return
775-- > any p = lmap p or
823-- > any p = lmap p or
824+-- > any p = fmap getAny . FL.foldMap (Any . p)
777-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
826-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
@@ -783,6 +832,8 @@ any predicate = Fold (\x a -> return $ x || predicate a) (return False) return
784-- | Return 'True' if the given element is present in the stream.
833-- | Return 'True' if the given element is present in the stream.
835+-- > elem a = any (== a)
786-- @since 0.7.0
837-- @since 0.7.0
787{-# INLINABLE elem #-}
838{-# INLINABLE elem #-}
788elem :: (Eq a, Monad m) => a -> Fold m a Bool
839elem :: (Eq a, Monad m) => a -> Fold m a Bool
@@ -790,6 +841,7 @@ elem a = any (a ==)
792-- > all p = lmap p and
843-- > all p = lmap p and
844+-- > all p = fmap getAll . FL.foldMap (All . p)
794-- | Returns 'True' if all elements of a stream satisfy a predicate.
846-- | Returns 'True' if all elements of a stream satisfy a predicate.
@@ -800,6 +852,8 @@ all predicate = Fold (\x a -> return $ x && predicate a) (return True) return
801-- | Returns 'True' if the given element is not present in the stream.
853-- | Returns 'True' if the given element is not present in the stream.
855+-- > notElem a = all (/= a)
803-- @since 0.7.0
857-- @since 0.7.0
804{-# INLINABLE notElem #-}
858{-# INLINABLE notElem #-}
805notElem :: (Eq a, Monad m) => a -> Fold m a Bool
859notElem :: (Eq a, Monad m) => a -> Fold m a Bool
@@ -807,6 +861,9 @@ notElem a = all (a /=)
808-- | Returns 'True' if all elements are 'True', 'False' otherwise
862-- | Returns 'True' if all elements are 'True', 'False' otherwise
864+-- > and = all (== True)
865+-- > and = fmap getAll . FL.foldMap All
810-- @since 0.7.0
867-- @since 0.7.0
811{-# INLINABLE and #-}
868{-# INLINABLE and #-}
812and :: Monad m => Fold m Bool Bool
869and :: Monad m => Fold m Bool Bool
@@ -814,6 +871,9 @@ and = Fold (\x a -> return $ x && a) (return True) return
815-- | Returns 'True' if any element is 'True', 'False' otherwise
872-- | Returns 'True' if any element is 'True', 'False' otherwise
874+-- > or = any (== True)
875+-- > or = fmap getAny . FL.foldMap Any
817-- @since 0.7.0
877-- @since 0.7.0
818{-# INLINABLE or #-}
878{-# INLINABLE or #-}
819or :: Monad m => Fold m Bool Bool
879or :: Monad m => Fold m Bool Bool