on master help sign in
Update docs/examples for folds in prelude
43623cbHarendra Kumar
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+7−6
@@ -234,17 +234,18 @@ relTimesWith = fmap snd . timesWith
234-- >>> Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)
234-- >>> Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)
235-- 5050
235-- 5050
236--
236--
237−-- @fold f = parse (Parser.fromFold f)@
238−--
239−-- Folds can never fail, therefore, they always produce a default value even
237+-- Folds never fail, therefore, they produce a default value even when no input
240−-- when no input is provided. It means we can always fold an empty stream and
238+-- is provided. It means we can always fold an empty stream and get a valid
241−-- get a valid result. For example:
239+-- result. For example:
242--
240--
243-- >>> Stream.fold Fold.sum Stream.nil
241-- >>> Stream.fold Fold.sum Stream.nil
244-- 0
242-- 0
245--
243--
246-- However, 'foldMany' on an empty stream results in an empty stream.
244-- However, 'foldMany' on an empty stream results in an empty stream.
247−-- Therefore, @fold f@ is not the same as @head . foldMany f@.
245+-- Therefore, @Stream.fold f@ is not the same as @Stream.head . Stream.foldMany
246+-- f@.
247+--
248+-- @fold f = Stream.parse (Parser.fromFold f)@
248--
249--
249-- @since 0.7.0
250-- @since 0.7.0
250{-# INLINE fold #-}
251{-# INLINE fold #-}
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+58−58
@@ -17,6 +17,9 @@
17
17
18module Streamly.Internal.Data.Stream.IsStream.Eliminate
18module Streamly.Internal.Data.Stream.IsStream.Eliminate
19 (
19 (
20+ -- * Running Examples
21+ -- $setup
22+
20 -- * Running a 'Fold'
23 -- * Running a 'Fold'
21 -- See "Streamly.Internal.Data.Fold".
24 -- See "Streamly.Internal.Data.Fold".
22 fold
25 fold
@@ -183,8 +186,9 @@ import Prelude hiding
183
186
184-- $setup
187-- $setup
185-- >>> :m
188-- >>> :m
189+-- >>> import Streamly.Prelude (SerialT)
186-- >>> import qualified Streamly.Prelude as Stream
190-- >>> import qualified Streamly.Prelude as Stream
187−-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream (parse)
191+-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream
188-- >>> import qualified Streamly.Internal.Data.Parser as Parser
192-- >>> import qualified Streamly.Internal.Data.Parser as Parser
189-- >>> import qualified Streamly.Data.Fold as Fold
193-- >>> import qualified Streamly.Data.Fold as Fold
190
194
@@ -362,7 +366,7 @@ parseK = parse
362-- Note:
366-- Note:
363--
367--
364-- @
368-- @
365−-- fold f = parse (Parser.fromFold f)
369+-- fold f = Stream.parse (Parser.fromFold f)
366-- @
370-- @
367--
371--
368-- @parse p@ is not the same as @head . parseMany p@ on an empty stream.
372-- @parse p@ is not the same as @head . parseMany p@ on an empty stream.
@@ -393,7 +397,7 @@ parse_ = parseD_ . PRK.fromParserK
393
397
394-- XXX this can utilize parallel mapping if we implement it as drain . mapM
398-- XXX this can utilize parallel mapping if we implement it as drain . mapM
395-- |
399-- |
396−-- > mapM_ = drain . mapM
400+-- > mapM_ = Stream.drain . Stream.mapM
397--
401--
398-- Apply a monadic action to each element of the stream and discard the output
402-- Apply a monadic action to each element of the stream and discard the output
399-- of the action. This is not really a pure transformation operation but a
403-- of the action. This is not really a pure transformation operation but a
@@ -406,11 +410,11 @@ mapM_ f m = S.mapM_ f $ toStreamS m
406
410
407-- |
411-- |
408-- > drain = mapM_ (\_ -> return ())
412-- > drain = mapM_ (\_ -> return ())
409−-- > drain = fold Fold.drain
413+-- > drain = Stream.fold Fold.drain
410--
414--
411-- Run a stream, discarding the results. By default it interprets the stream
415-- Run a stream, discarding the results. By default it interprets the stream
412-- as 'SerialT', to run other types of streams use the type adapting
416-- as 'SerialT', to run other types of streams use the type adapting
413−-- combinators for example @drain . 'asyncly'@.
417+-- combinators for example @Stream.drain . 'asyncly'@.
414--
418--
415-- @since 0.7.0
419-- @since 0.7.0
416{-# INLINE drain #-}
420{-# INLINE drain #-}
@@ -418,8 +422,8 @@ drain :: Monad m => SerialT m a -> m ()
418drain = P.drain
422drain = P.drain
419
423
420-- |
424-- |
421−-- > drainN n = drain . take n
425+-- > drainN n = Stream.drain . Stream.take n
422−-- > drainN n = fold (Fold.take n Fold.drain)
426+-- > drainN n = Stream.fold (Fold.take n Fold.drain)
423--
427--
424-- Run maximum up to @n@ iterations of a stream.
428-- Run maximum up to @n@ iterations of a stream.
425--
429--
@@ -440,7 +444,7 @@ runN :: Monad m => Int -> SerialT m a -> m ()
440runN = drainN
444runN = drainN
441
445
442-- |
446-- |
443−-- > drainWhile p = drain . takeWhile p
447+-- > drainWhile p = Stream.drain . Stream.takeWhile p
444--
448--
445-- Run a stream as long as the predicate holds true.
449-- Run a stream as long as the predicate holds true.
446--
450--
@@ -472,7 +476,7 @@ runStream = drain
472
476
473-- | Determine whether the stream is empty.
477-- | Determine whether the stream is empty.
474--
478--
475−-- > null = fold Fold.null
479+-- > null = Stream.fold Fold.null
476--
480--
477-- @since 0.1.1
481-- @since 0.1.1
478{-# INLINE null #-}
482{-# INLINE null #-}
@@ -482,7 +486,7 @@ null = S.null . toStreamS
482-- | Extract the first element of the stream, if any.
486-- | Extract the first element of the stream, if any.
483--
487--
484-- > head = (!! 0)
488-- > head = (!! 0)
485−-- > head = fold Fold.head
489+-- > head = Stream.fold Fold.head
486--
490--
487-- @since 0.1.0
491-- @since 0.1.0
488{-# INLINE head #-}
492{-# INLINE head #-}
@@ -499,7 +503,7 @@ headElse :: Monad m => a -> SerialT m a -> m a
499headElse x = D.headElse x . toStreamD
503headElse x = D.headElse x . toStreamD
500
504
501-- |
505-- |
502−-- > tail = fmap (fmap snd) . uncons
506+-- > tail = fmap (fmap snd) . Stream.uncons
503--
507--
504-- Extract all but the first element of the stream, if any.
508-- Extract all but the first element of the stream, if any.
505--
509--
@@ -517,8 +521,8 @@ init m = K.init (K.adapt m)
517
521
518-- | Extract the last element of the stream, if any.
522-- | Extract the last element of the stream, if any.
519--
523--
520−-- > last xs = xs !! (length xs - 1)
524+-- > last xs = xs !! (Stream.length xs - 1)
521−-- > last = fold Fold.last
525+-- > last = Stream.fold Fold.last
522--
526--
523-- @since 0.1.1
527-- @since 0.1.1
524{-# INLINE last #-}
528{-# INLINE last #-}
@@ -527,7 +531,7 @@ last m = S.last $ toStreamS m
527
531
528-- | Determine whether an element is present in the stream.
532-- | Determine whether an element is present in the stream.
529--
533--
530−-- > elem = fold Fold.elem
534+-- > elem = Stream.fold Fold.elem
531--
535--
532-- @since 0.1.0
536-- @since 0.1.0
533{-# INLINE elem #-}
537{-# INLINE elem #-}
@@ -536,7 +540,7 @@ elem e m = S.elem e (toStreamS m)
536
540
537-- | Determine whether an element is not present in the stream.
541-- | Determine whether an element is not present in the stream.
538--
542--
539−-- > notElem = fold Fold.length
543+-- > notElem = Stream.fold Fold.length
540--
544--
541-- @since 0.1.0
545-- @since 0.1.0
542{-# INLINE notElem #-}
546{-# INLINE notElem #-}
@@ -552,7 +556,7 @@ length = foldl' (\n _ -> n + 1) 0
552
556
553-- | Determine whether all elements of a stream satisfy a predicate.
557-- | Determine whether all elements of a stream satisfy a predicate.
554--
558--
555−-- > all = fold Fold.all
559+-- > all = Stream.fold Fold.all
556--
560--
557-- @since 0.1.0
561-- @since 0.1.0
558{-# INLINE all #-}
562{-# INLINE all #-}
@@ -561,7 +565,7 @@ all p m = S.all p (toStreamS m)
561
565
562-- | Determine whether any of the elements of a stream satisfy a predicate.
566-- | Determine whether any of the elements of a stream satisfy a predicate.
563--
567--
564−-- > any = fold Fold.any
568+-- > any = Stream.fold Fold.any
565--
569--
566-- @since 0.1.0
570-- @since 0.1.0
567{-# INLINE any #-}
571{-# INLINE any #-}
@@ -570,7 +574,7 @@ any p m = S.any p (toStreamS m)
570
574
571-- | Determines if all elements of a boolean stream are True.
575-- | Determines if all elements of a boolean stream are True.
572--
576--
573−-- > and = fold Fold.and
577+-- > and = Stream.fold Fold.and
574--
578--
575-- @since 0.5.0
579-- @since 0.5.0
576{-# INLINE and #-}
580{-# INLINE and #-}
@@ -579,7 +583,7 @@ and = all (==True)
579
583
580-- | Determines whether at least one element of a boolean stream is True.
584-- | Determines whether at least one element of a boolean stream is True.
581--
585--
582−-- > or = fold Fold.or
586+-- > or = Stream.fold Fold.or
583--
587--
584-- @since 0.5.0
588-- @since 0.5.0
585{-# INLINE or #-}
589{-# INLINE or #-}
@@ -590,7 +594,7 @@ or = any (==True)
590-- the stream is empty. Note that this is not numerically stable for floating
594-- the stream is empty. Note that this is not numerically stable for floating
591-- point numbers.
595-- point numbers.
592--
596--
593−-- > sum = fold Fold.sum
597+-- > sum = Stream.fold Fold.sum
594--
598--
595-- @since 0.1.0
599-- @since 0.1.0
596{-# INLINE sum #-}
600{-# INLINE sum #-}
@@ -600,7 +604,7 @@ sum = foldl' (+) 0
600-- | Determine the product of all elements of a stream of numbers. Returns @1@
604-- | Determine the product of all elements of a stream of numbers. Returns @1@
601-- when the stream is empty.
605-- when the stream is empty.
602--
606--
603−-- > product = fold Fold.product
607+-- > product = Stream.fold Fold.product
604--
608--
605-- @since 0.1.1
609-- @since 0.1.1
606{-# INLINE product #-}
610{-# INLINE product #-}
@@ -609,7 +613,7 @@ product = foldl' (*) 1
609
613
610-- | Fold a stream of monoid elements by appending them.
614-- | Fold a stream of monoid elements by appending them.
611--
615--
612−-- > mconcat = fold Fold.mconcat
616+-- > mconcat = Stream.fold Fold.mconcat
613--
617--
614-- /Pre-release/
618-- /Pre-release/
615{-# INLINE mconcat #-}
619{-# INLINE mconcat #-}
@@ -619,7 +623,7 @@ mconcat = foldr mappend mempty
619-- |
623-- |
620-- @
624-- @
621-- minimum = 'minimumBy' compare
625-- minimum = 'minimumBy' compare
622− -- minimum = fold Fold.minimum
626+ -- minimum = Stream.fold Fold.minimum
623-- @
627-- @
624--
628--
625-- Determine the minimum element in a stream.
629-- Determine the minimum element in a stream.
@@ -632,7 +636,7 @@ minimum m = S.minimum (toStreamS m)
632-- | Determine the minimum element in a stream using the supplied comparison
636-- | Determine the minimum element in a stream using the supplied comparison
633-- function.
637-- function.
634--
638--
635−-- > minimumBy = fold Fold.minimumBy
639+-- > minimumBy = Stream.fold Fold.minimumBy
636--
640--
637-- @since 0.6.0
641-- @since 0.6.0
638{-# INLINE minimumBy #-}
642{-# INLINE minimumBy #-}
@@ -642,7 +646,7 @@ minimumBy cmp m = S.minimumBy cmp (toStreamS m)
642-- |
646-- |
643-- @
647-- @
644-- maximum = 'maximumBy' compare
648-- maximum = 'maximumBy' compare
645−-- maximum = fold Fold.maximum
649+-- maximum = Stream.fold Fold.maximum
646-- @
650-- @
647--
651--
648-- Determine the maximum element in a stream.
652-- Determine the maximum element in a stream.
@@ -655,7 +659,7 @@ maximum = P.maximum
655-- | Determine the maximum element in a stream using the supplied comparison
659-- | Determine the maximum element in a stream using the supplied comparison
656-- function.
660-- function.
657--
661--
658−-- > maximumBy = fold Fold.maximumBy
662+-- > maximumBy = Stream.fold Fold.maximumBy
659--
663--
660-- @since 0.6.0
664-- @since 0.6.0
661{-# INLINE maximumBy #-}
665{-# INLINE maximumBy #-}
@@ -684,8 +688,8 @@ m !! i = toStreamS m S.!! i
684-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
688-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
685-- first pair where the key equals the given value @a@.
689-- first pair where the key equals the given value @a@.
686--
690--
687−-- > lookup = snd <$> find ((==) . fst)
691+-- > lookup = snd <$> Stream.find ((==) . fst)
688−-- > lookup = fold Fold.lookup
692+-- > lookup = Stream.fold Fold.lookup
689--
693--
690-- @since 0.5.0
694-- @since 0.5.0
691{-# INLINE lookup #-}
695{-# INLINE lookup #-}
@@ -695,7 +699,7 @@ lookup a m = S.lookup a (toStreamS m)
695-- | Like 'findM' but with a non-monadic predicate.
699-- | Like 'findM' but with a non-monadic predicate.
696--
700--
697-- > find p = findM (return . p)
701-- > find p = findM (return . p)
698−-- > find = fold Fold.find
702+-- > find = Stream.fold Fold.find
699--
703--
700-- @since 0.5.0
704-- @since 0.5.0
701{-# INLINE find #-}
705{-# INLINE find #-}
@@ -704,7 +708,7 @@ find p m = S.find p (toStreamS m)
704
708
705-- | Returns the first element that satisfies the given predicate.
709-- | Returns the first element that satisfies the given predicate.
706--
710--
707−-- > findM = fold Fold.findM
711+-- > findM = Stream.fold Fold.findM
708--
712--
709-- @since 0.6.0
713-- @since 0.6.0
710{-# INLINE findM #-}
714{-# INLINE findM #-}
@@ -713,7 +717,7 @@ findM p m = S.findM p (toStreamS m)
713
717
714-- | Returns the first index that satisfies the given predicate.
718-- | Returns the first index that satisfies the given predicate.
715--
719--
716−-- > findIndex = fold Fold.findIndex
720+-- > findIndex = Stream.fold Fold.findIndex
717--
721--
718-- @since 0.5.0
722-- @since 0.5.0
719{-# INLINE findIndex #-}
723{-# INLINE findIndex #-}
@@ -722,7 +726,7 @@ findIndex p = head . findIndices p
722
726
723-- | Returns the first index where a given value is found in the stream.
727-- | Returns the first index where a given value is found in the stream.
724--
728--
725−-- > elemIndex a = findIndex (== a)
729+-- > elemIndex a = Stream.findIndex (== a)
726--
730--
727-- @since 0.5.0
731-- @since 0.5.0
728{-# INLINE elemIndex #-}
732{-# INLINE elemIndex #-}
@@ -735,7 +739,7 @@ elemIndex a = findIndex (== a)
735
739
736-- |
740-- |
737-- @
741-- @
738−-- toList = S.foldr (:) []
742+-- toList = Stream.foldr (:) []
739-- @
743-- @
740--
744--
741-- Convert a stream into a list in the underlying monad. The list can be
745-- Convert a stream into a list in the underlying monad. The list can be
@@ -752,7 +756,7 @@ toList = P.toList
752
756
753-- |
757-- |
754-- @
758-- @
755−-- toListRev = S.foldl' (flip (:)) []
759+-- toListRev = Stream.foldl' (flip (:)) []
756-- @
760-- @
757--
761--
758-- Convert a stream into a list in reverse order in the underlying monad.
762-- Convert a stream into a list in reverse order in the underlying monad.
@@ -787,7 +791,7 @@ toHandle h = go
787-- | Convert a stream to a pure stream.
791-- | Convert a stream to a pure stream.
788--
792--
789-- @
793-- @
790−-- toStream = foldr cons nil
794+-- toStream = Stream.foldr Stream.cons Stream.nil
791-- @
795-- @
792--
796--
793-- /Pre-release/
797-- /Pre-release/
@@ -799,7 +803,7 @@ toStream = foldr K.cons K.nil
799-- | Convert a stream to a pure stream in reverse order.
803-- | Convert a stream to a pure stream in reverse order.
800--
804--
801-- @
805-- @
802−-- toStreamRev = foldl' (flip cons) nil
806+-- toStreamRev = Stream.foldl' (flip Stream.cons) Stream.nil
803-- @
807-- @
804--
808--
805-- /Pre-release/
809-- /Pre-release/
@@ -825,10 +829,18 @@ toStreamRev = foldl' (flip K.cons) K.nil
825-- The @.@ at the end of the operator is a mnemonic for termination of the
829-- The @.@ at the end of the operator is a mnemonic for termination of the
826-- stream.
830-- stream.
827--
831--
828−-- @
832+-- In the example below, each stage introduces a delay of 1 sec but output is
833+-- printed every second because both stages are concurrent.
834+--
835+-- >>> import Control.Concurrent (threadDelay)
836+-- >>> import Streamly.Prelude ((|$.))
837+-- >>> :{
829−-- S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
838+-- Stream.foldlM' (\_ a -> threadDelay 1000000 >> print a) (return ())
830−-- |$. S.repeatM (threadDelay 1000000 >> return 1)
839+-- |$. Stream.replicateM 3 (threadDelay 1000000 >> return 1)
831−-- @
840+-- :}
841+-- 1
842+-- 1
843+-- 1
832--
844--
833-- /Concurrent/
845-- /Concurrent/
834--
846--
@@ -850,13 +862,9 @@ infixr 0 |$.
850foldAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
862foldAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
851foldAsync = (|$.)
863foldAsync = (|$.)
852
864
853−-- | Parallel reverse function application operator for applying a run or fold
865+-- | Same as '|$.' but with arguments reversed.
854−-- functions to a stream. Just like '|$.' except that the operands are reversed.
855--
866--
856−-- @
867+-- > (|&.) = flip (|$.)
857−-- S.repeatM (threadDelay 1000000 >> return 1)
858−-- |&. S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
859−-- @
860--
868--
861-- /Concurrent/
869-- /Concurrent/
862--
870--
@@ -876,10 +884,8 @@ infixl 1 |&.
876-- | Returns 'True' if the first stream is the same as or a prefix of the
884-- | Returns 'True' if the first stream is the same as or a prefix of the
877-- second. A stream is a prefix of itself.
885-- second. A stream is a prefix of itself.
878--
886--
879−-- @
880−-- > S.isPrefixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
887+-- >>> Stream.isPrefixOf (Stream.fromList "hello") (Stream.fromList "hello" :: SerialT IO Char)
881-- True
888-- True
882−-- @
883--
889--
884-- @since 0.6.0
890-- @since 0.6.0
885{-# INLINE isPrefixOf #-}
891{-# INLINE isPrefixOf #-}
@@ -889,10 +895,8 @@ isPrefixOf m1 m2 = D.isPrefixOf (toStreamD m1) (toStreamD m2)
889-- | Returns 'True' if the first stream is an infix of the second. A stream is
895-- | Returns 'True' if the first stream is an infix of the second. A stream is
890-- considered an infix of itself.
896-- considered an infix of itself.
891--
897--
892−-- @
893−-- > S.isInfixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
898+-- > Stream.isInfixOf (Stream.fromList "hello") (Stream.fromList "hello" :: SerialT IO Char)
894-- True
899-- True
895−-- @
896--
900--
897-- Space: @O(n)@ worst case where @n@ is the length of the infix.
901-- Space: @O(n)@ worst case where @n@ is the length of the infix.
898--
902--
@@ -928,10 +932,8 @@ isInfixOf infx stream = do
928-- | Returns 'True' if the first stream is a suffix of the second. A stream is
932-- | Returns 'True' if the first stream is a suffix of the second. A stream is
929-- considered a suffix of itself.
933-- considered a suffix of itself.
930--
934--
931−-- @
932−-- > S.isSuffixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
935+-- >>> Stream.isSuffixOf (Stream.fromList "hello") (Stream.fromList "hello" :: SerialT IO Char)
933-- True
936-- True
934−-- @
935--
937--
936-- Space: @O(n)@, buffers entire input stream and the suffix.
938-- Space: @O(n)@, buffers entire input stream and the suffix.
937--
939--
@@ -947,10 +949,8 @@ isSuffixOf suffix stream = reverse suffix `isPrefixOf` reverse stream
947-- the second stream. The elements do not have to occur consecutively. A stream
949-- the second stream. The elements do not have to occur consecutively. A stream
948-- is a subsequence of itself.
950-- is a subsequence of itself.
949--
951--
950−-- @
951−-- > S.isSubsequenceOf (S.fromList "hlo") (S.fromList "hello" :: SerialT IO Char)
952+-- >>> Stream.isSubsequenceOf (Stream.fromList "hlo") (Stream.fromList "hello" :: SerialT IO Char)
952-- True
953-- True
953−-- @
954--
954--
955-- @since 0.6.0
955-- @since 0.6.0
956{-# INLINE isSubsequenceOf #-}
956{-# INLINE isSubsequenceOf #-}
src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+2−2
@@ -281,8 +281,8 @@ foldManyPost f m = D.fromStreamD $ D.foldManyPost f (D.toStreamD m)
281-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList []
281-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList []
282-- []
282-- []
283--
283--
284−-- Note @foldMany (take 0)@ would result in an infinite loop in a non-empty
284+-- Note @Stream.foldMany (Fold.take 0)@ would result in an infinite loop in a
285−-- stream.
285+-- non-empty stream.
286--
286--
287-- @since 0.8.0
287-- @since 0.8.0
288--
288--
src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+28−13
@@ -566,6 +566,9 @@ trace_ eff = Serial.mapM (\x -> eff >> return x)
566
566
567-- | Scan a stream using the given monadic fold.
567-- | Scan a stream using the given monadic fold.
568--
568--
569+-- >>> Stream.toList $ Stream.takeWhile (< 10) $ Stream.scan Fold.sum (Stream.fromList [1..10])
570+-- [0,1,3,6]
571+--
569-- @since 0.7.0
572-- @since 0.7.0
570{-# INLINE scan #-}
573{-# INLINE scan #-}
571scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
574scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
@@ -573,6 +576,19 @@ scan = P.scanOnce
573
576
574-- | Postscan a stream using the given monadic fold.
577-- | Postscan a stream using the given monadic fold.
575--
578--
579+-- The following example extracts the input stream up to a point where the
580+-- running average of elements is no more than 10:
581+--
582+-- >>> import Data.Maybe (fromJust)
583+-- >>> let avg = Fold.teeWith (/) Fold.sum (fmap fromIntegral Fold.length)
584+-- >>> :{
585+-- Stream.toList
586+-- $ Stream.map (fromJust . fst)
587+-- $ Stream.takeWhile (\(_,x) -> x <= 10)
588+-- $ Stream.postscan (Fold.tee Fold.last avg) (Stream.enumerateFromTo 1.0 100.0)
589+-- :}
590+-- [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]
591+--
576-- @since 0.7.0
592-- @since 0.7.0
577{-# INLINE postscan #-}
593{-# INLINE postscan #-}
578postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
594postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
@@ -1473,11 +1489,16 @@ rights = fmap (fromRight undefined) . filter isRight
1473-- 1 second delay.
1489-- 1 second delay.
1474--
1490--
1475--
1491--
1476−-- @
1492+-- >>> import Control.Concurrent (threadDelay)
1493+-- >>> import Streamly.Prelude ((|$))
1494+-- >>> :{
1477−-- drain $
1495+-- Stream.drain $
1478−-- S.mapM (\\x -> threadDelay 1000000 >> print x)
1496+-- Stream.mapM (\x -> threadDelay 1000000 >> print x)
1479−-- |$ S.repeatM (threadDelay 1000000 >> return 1)
1497+-- |$ Stream.replicateM 3 (threadDelay 1000000 >> return 1)
1480−-- @
1498+-- :}
1499+-- 1
1500+-- 1
1501+-- 1
1481--
1502--
1482-- /Concurrent/
1503-- /Concurrent/
1483--
1504--
@@ -1500,15 +1521,9 @@ applyAsync :: (IsStream t, MonadAsync m)
1500 => (t m a -> t m b) -> (t m a -> t m b)
1521 => (t m a -> t m b) -> (t m a -> t m b)
1501applyAsync = (|$)
1522applyAsync = (|$)
1502
1523
1503−-- | Parallel reverse function application operator for streams; just like the
1524+-- | Same as '|$' but with arguments reversed.
1504−-- regular reverse function application operator '&' except that it is
1505−-- concurrent.
1506--
1525--
1507−-- @
1526+-- (|&) = flip (|$)
1508−-- drain $
1509−-- S.repeatM (threadDelay 1000000 >> return 1)
1510−-- |& S.mapM (\\x -> threadDelay 1000000 >> print x)
1511−-- @
1512--
1527--
1513-- /Concurrent/
1528-- /Concurrent/
1514--
1529--
src/Streamly/Prelude.hs+2−49
@@ -1135,48 +1135,8 @@ import Streamly.Internal.Data.Stream.IsStream
1135
1135
1136-- $runningfolds
1136-- $runningfolds
1137--
1137--
1138−-- "Streamly.Data.Fold" module defines composable left folds which can be combined
1138+-- See "Streamly.Data.Fold" for an overview of composable folds. All folds in
1139−-- together in many interesting ways. Those folds can be run using 'fold'.
1139+-- this module can be expressed in terms of composable folds using 'fold'.
1140−-- The following two ways of folding are equivalent in functionality and
1141−-- performance,
1142−--
1143−-- >>> Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)
1144−-- 5050
1145−-- >>> Stream.sum (Stream.enumerateFromTo 1 100)
1146−-- 5050
1147−--
1148−-- However, left folds cannot terminate early even if it does not need to
1149−-- consume more input to determine the result. Therefore, the performance is
1150−-- equivalent only for full folds like 'sum' and 'length'. For partial folds
1151−-- like 'head' or 'any' the the folds defined in this module may be much more
1152−-- efficient because they are implemented as right folds that terminate as soon
1153−-- as we get the result. Note that when a full fold is composed with a partial
1154−-- fold in parallel the performance is not impacted as we anyway have to
1155−-- consume the whole stream due to the full fold.
1156−--
1157−-- >>> Stream.head (1 `Stream.cons` undefined)
1158−-- Just 1
1159−-- >>> Stream.fold Fold.head (1 `Stream.cons` undefined)
1160−-- Just 1
1161−--
1162−-- However, we can wrap the fold in a scan to convert it into a lazy stream of
1163−-- fold steps. We can then terminate the stream whenever we want. For example,
1164−--
1165−-- >>> Stream.toList $ Stream.take 1 $ Stream.scan Fold.head (1 `Stream.cons` undefined)
1166−-- [Nothing]
1167−--
1168−-- The following example extracts the input stream up to a point where the
1169−-- running average of elements is no more than 10:
1170−--
1171−-- >>> import Data.Maybe (fromJust)
1172−-- >>> let avg = Fold.teeWith (/) Fold.sum (fmap fromIntegral Fold.length)
1173−-- >>> :{
1174−-- Stream.toList
1175−-- $ Stream.map (fromJust . fst)
1176−-- $ Stream.takeWhile (\(_,x) -> x <= 10)
1177−-- $ Stream.postscan (Fold.tee Fold.last avg) (Stream.enumerateFromTo 1.0 100.0)
1178−-- :}
1179−-- [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]
1180--
1140--
1181-- $application
1141-- $application
1182--
1142--
@@ -1186,13 +1146,6 @@ import Streamly.Internal.Data.Stream.IsStream
1186-- operators applying stream processing functions such that each stage of the
1146-- operators applying stream processing functions such that each stage of the
1187-- stream can run in parallel. The operators start with a @|@; we can read '|$'
1147-- stream can run in parallel. The operators start with a @|@; we can read '|$'
1188-- as "@parallel dollar@" to remember that @|@ comes before '$'.
1148-- as "@parallel dollar@" to remember that @|@ comes before '$'.
1189−--
1190−-- Imports for the code snippets below:
1191−--
1192−-- @
1193−-- import qualified Streamly.Prelude as S
1194−-- import Control.Concurrent
1195−-- @
1196
1149
1197-- $concurrency
1150-- $concurrency
1198--
1151--