@@ -60,6 +60,7 @@ module Streamly.Internal.Data.Fold
6060
6161 -- ** Full Folds (Monoidal)
6262 , mconcat
63+ , mconcatTo
6364 , foldMap
6465 , foldMapM
6566
@@ -386,6 +387,8 @@ _Fold1 step = Fold step_ (return Nothing') (return . toMaybe)
386387-- | A fold that drains all its input, running the effects and discarding the
387388-- results.
388389--
390+-- > drain = drainBy (const (return ()))
391+--
389392-- @since 0.7.0
390393{-# INLINABLE drain #-}
391394drain :: Monad m => Fold m a ()
@@ -397,6 +400,7 @@ drain = Fold step begin done
397400
398401-- |
399402-- > drainBy f = lmapM f drain
403+-- > drainBy = FL.foldMapM (void . f)
400404--
401405-- Drain all input after passing it through a monadic function. This is the
402406-- dual of mapM_ on stream producers.
@@ -412,6 +416,8 @@ drainBy2 f = Fold2 (const (void . f)) (\_ -> return ()) return
412416
413417-- | Extract the last element of the input stream, if any.
414418--
419+-- > last = fmap getLast $ FL.foldMap (Last . Just)
420+--
415421-- @since 0.7.0
416422{-# INLINABLE last #-}
417423last :: Monad m => Fold m a (Maybe a)
@@ -423,6 +429,8 @@ last = _Fold1 (flip const)
423429
424430-- | Like 'length', except with a more general 'Num' return value
425431--
432+-- > genericLength = fmap getSum $ foldMap (Sum . const 1)
433+--
426434-- @since 0.7.0
427435{-# INLINABLE genericLength #-}
428436genericLength :: (Monad m, Num b) => Fold m a b
@@ -430,6 +438,8 @@ genericLength = Fold (\n _ -> return $ n + 1) (return 0) return
430438
431439-- | Determine the length of the input stream.
432440--
441+-- > length = fmap getSum $ foldMap (Sum . const 1)
442+--
433443-- @since 0.7.0
434444{-# INLINABLE length #-}
435445length :: Monad m => Fold m a Int
@@ -439,14 +449,18 @@ length = genericLength
439449-- identity (@0@) when the stream is empty. Note that this is not numerically
440450-- stable for floating point numbers.
441451--
452+-- > sum = fmap getSum $ FL.foldMap Sum
453+--
442454-- @since 0.7.0
443−{-# INLINABLE sum #-}
455+{-# INLINE sum #-}
444456sum :: (Monad m, Num a) => Fold m a a
445457sum = Fold (\x a -> return $ x + a) (return 0) return
446458
447459-- | Determine the product of all elements of a stream of numbers. Returns
448460-- multiplicative identity (@1@) when the stream is empty.
449461--
462+-- > product = fmap getProduct $ FL.foldMap Product
463+--
450464-- @since 0.7.0
451465{-# INLINABLE product #-}
452466product :: (Monad m, Num a) => Fold m a a
@@ -475,6 +489,8 @@ maximumBy cmp = _Fold1 max'
475489--
476490-- Determine the maximum element in a stream.
477491--
492+-- Compare with @FL.foldMap Max@.
493+--
478494-- @since 0.7.0
479495{-# INLINABLE maximum #-}
480496maximum :: (Monad m, Ord a) => Fold m a (Maybe a)
@@ -494,6 +510,12 @@ minimumBy cmp = _Fold1 min'
494510-- | Determine the minimum element in a stream using the supplied comparison
495511-- function.
496512--
513+-- @
514+-- minimum = 'minimumBy' compare
515+-- @
516+--
517+-- Compare with @FL.foldMap Min@.
518+--
497519-- @since 0.7.0
498520{-# INLINABLE minimum #-}
499521minimum :: (Monad m, Ord a) => Fold m a (Maybe a)
@@ -591,18 +613,31 @@ rollingHashFirstN n = ltake n rollingHash
591613-- Monoidal left folds
592614------------------------------------------------------------------------------
593615
616+-- | 'mappend' the elements of an input stream to a provided starting value.
617+--
618+-- > S.fold (FL.mconcatTo 10) (S.map Sum $ S.enumerateFromTo 1 10)
619+--
620+-- This could be faster than (fmap (m0 <>) FL.mconcat) especially when we have
621+-- to perform the operation many times.
622+--
623+-- /Internal/
624+--
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
628+
594629-- | Fold an input stream consisting of monoidal elements using 'mappend'
595630-- and 'mempty'.
596631--
597632-- > S.fold FL.mconcat (S.map Sum $ S.enumerateFromTo 1 10)
598633--
599634-- @since 0.7.0
600−{-# INLINABLE mconcat #-}
635+{-# INLINE mconcat #-}
601636mconcat :: (Monad m, Monoid a) => Fold m a a
602−mconcat = Fold (\x a -> return $ mappend x a) (return mempty) return
637+mconcat = mconcatTo mempty
603638
604639-- |
605−-- > foldMap f = map f mconcat
640+-- > foldMap f = lmap f mconcat
606641--
607642-- Make a fold from a pure function that folds the output of the function
608643-- using 'mappend' and 'mempty'.
@@ -615,7 +650,7 @@ foldMap :: (Monad m, Monoid b) => (a -> b) -> Fold m a b
615650foldMap f = lmap f mconcat
616651
617652-- |
618−-- > foldMapM f = mapM f mconcat
653+-- > foldMapM f = lmapM f mconcat
619654--
620655-- Make a fold from a monadic function that folds the output of the function
621656-- using 'mappend' and 'mempty'.
@@ -698,6 +733,8 @@ index = genericIndex
698733
699734-- | Extract the first element of the stream, if any.
700735--
736+-- > head = fmap getFirst $ FL.foldMap (First . Just)
737+--
701738-- @since 0.7.0
702739{-# INLINABLE head #-}
703740head :: Monad m => Fold m a (Maybe a)
@@ -705,6 +742,11 @@ head = _Fold1 const
705742
706743-- | Returns the first element that satisfies the given predicate.
707744--
745+-- @
746+-- find p = fmap getFirst $
747+-- foldMap (\x -> First (if p x then Just x else Nothing))
748+-- @
749+--
708750-- @since 0.7.0
709751{-# INLINABLE find #-}
710752find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
@@ -720,6 +762,8 @@ find predicate = Fold step (return Nothing') (return . toMaybe)
720762-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
721763-- first pair where the key equals the given value @a@.
722764--
765+-- > lookup = snd <$> find ((==) . fst)
766+--
723767-- @since 0.7.0
724768{-# INLINABLE lookup #-}
725769lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
@@ -755,6 +799,8 @@ findIndex predicate = Fold step (return $ Left' 0) (return . hush)
755799
756800-- | Returns the first index where a given value is found in the stream.
757801--
802+-- > elemIndex a = findIndex (== a)
803+--
758804-- @since 0.7.0
759805{-# INLINABLE elemIndex #-}
760806elemIndex :: (Eq a, Monad m) => a -> Fold m a (Maybe Int)
@@ -766,6 +812,8 @@ elemIndex a = findIndex (a ==)
766812
767813-- | Return 'True' if the input stream is empty.
768814--
815+-- > null = fmap isJust head
816+--
769817-- @since 0.7.0
770818{-# INLINABLE null #-}
771819null :: Monad m => Fold m a Bool
@@ -773,6 +821,7 @@ null = Fold (\_ _ -> return False) (return True) return
773821
774822-- |
775823-- > any p = lmap p or
824+-- > any p = fmap getAny . FL.foldMap (Any . p)
776825--
777826-- | Returns 'True' if any of the elements of a stream satisfies a predicate.
778827--
@@ -783,6 +832,8 @@ any predicate = Fold (\x a -> return $ x || predicate a) (return False) return
783832
784833-- | Return 'True' if the given element is present in the stream.
785834--
835+-- > elem a = any (== a)
836+--
786837-- @since 0.7.0
787838{-# INLINABLE elem #-}
788839elem :: (Eq a, Monad m) => a -> Fold m a Bool
@@ -790,6 +841,7 @@ elem a = any (a ==)
790841
791842-- |
792843-- > all p = lmap p and
844+-- > all p = fmap getAll . FL.foldMap (All . p)
793845--
794846-- | Returns 'True' if all elements of a stream satisfy a predicate.
795847--
@@ -800,6 +852,8 @@ all predicate = Fold (\x a -> return $ x && predicate a) (return True) return
800852
801853-- | Returns 'True' if the given element is not present in the stream.
802854--
855+-- > notElem a = all (/= a)
856+--
803857-- @since 0.7.0
804858{-# INLINABLE notElem #-}
805859notElem :: (Eq a, Monad m) => a -> Fold m a Bool
@@ -807,6 +861,9 @@ notElem a = all (a /=)
807861
808862-- | Returns 'True' if all elements are 'True', 'False' otherwise
809863--
864+-- > and = all (== True)
865+-- > and = fmap getAll . FL.foldMap All
866+--
810867-- @since 0.7.0
811868{-# INLINABLE and #-}
812869and :: Monad m => Fold m Bool Bool
@@ -814,6 +871,9 @@ and = Fold (\x a -> return $ x && a) (return True) return
814871
815872-- | Returns 'True' if any element is 'True', 'False' otherwise
816873--
874+-- > or = any (== True)
875+-- > or = fmap getAny . FL.foldMap Any
876+--
817877-- @since 0.7.0
818878{-# INLINABLE or #-}
819879or :: Monad m => Fold m Bool Bool