on master help sign in
Add toList fold to Data.Stream module
commit430f06defd06d81bd56cdb4b179261f2059d4cdf authorHarendra Kumar <harendra@composewell.com> dateMon 6 Mar 2023, 23:15 (4 years ago) parentf4698a8
2 files changed+61−6
core/src/Streamly/Data/Stream.hs+12−5 core/src/Streamly/Internal/Data/Stream/StreamD/Type.hs+49−1
core/src/Streamly/Data/Stream.hs+12−5
@@ -232,7 +232,7 @@ module Streamly.Data.Stream
232232 -- ending in the general shape @Stream m a -> m (b, Stream m a)@
233233 , uncons
234234
235− -- ** Folding
235+ -- ** Strict Left Folds
236236 -- XXX Need to have a general parse operation here which can be used to
237237 -- express all others.
238238 , fold -- XXX rename to run? We can have a Stream.run and Fold.run.
@@ -248,15 +248,22 @@ module Streamly.Data.Stream
248248 , parse
249249 -- , parseBreak
250250
251− -- -- ** Lazy Right Folds
252− -- Consuming a stream to build a right associated expression, suitable
251+ -- ** Lazy Right Folds
252+ -- | Consuming a stream to build a right associated expression, suitable
253253 -- for lazy evaluation. Evaluation of the input happens when the output of
254254 -- the fold is evaluated, the fold output is a lazy thunk.
255255 --
256256 -- This is suitable for stream transformation operations, for example,
257257 -- operations like mapping a function over the stream.
258− -- , foldrM
259− -- , foldr
258+ , foldrM
259+ , foldr
260+
261+ -- ** Specific Folds
262+ -- | Usually you can use the folds in "Streamly.Data.Fold". However, some
263+ -- folds that may be commonly used or may have an edge in performance in
264+ -- some cases are provided here.
265+ -- , drain
266+ , toList
260267
261268 -- * Mapping
262269 -- | Stateless one-to-one transformations. Use 'fmap' for mapping a pure
core/src/Streamly/Internal/Data/Stream/StreamD/Type.hs+49−1
@@ -677,7 +677,16 @@ foldl' fstep begin = foldlM' (\b a -> return (fstep b a)) (return begin)
677677-- Special folds
678678------------------------------------------------------------------------------
679679
680−-- | Run a streaming composition, discard the results.
680+-- >>> drain = mapM_ (\_ -> return ())
681+
682+-- |
683+-- Definitions:
684+--
685+-- >>> drain = Stream.fold Fold.drain
686+-- >>> drain = Stream.foldrM (\_ xs -> xs) (return ())
687+--
688+-- Run a stream, discarding the results.
689+--
681690{-# INLINE_LATE drain #-}
682691drain :: Monad m => Stream m a -> m ()
683692-- drain = foldrM (\_ xs -> xs) (return ())
@@ -694,6 +703,45 @@ drain (Stream step state) = go SPEC state
694703-- To Containers
695704------------------------------------------------------------------------------
696705
706+-- This toList impl is faster (30% on streaming-benchmarks) than the
707+-- corresponding left fold. The left fold retains an additional argument in the
708+-- recursive loop.
709+--
710+-- Core for the right fold loop:
711+--
712+-- main_$s$wgo1
713+-- = \ sc_s3e6 sc1_s3e5 ->
714+-- case ># sc1_s3e5 100000# of {
715+-- __DEFAULT ->
716+-- case main_$s$wgo1 sc_s3e6 (+# sc1_s3e5 1#) of
717+--
718+-- Core for the left fold loop:
719+--
720+-- main_$s$wgo1
721+-- = \ sc_s3oT sc1_s3oS sc2_s3oR ->
722+-- case sc2_s3oR of fs2_a2lw { __DEFAULT ->
723+-- case ># sc1_s3oS 100000# of {
724+-- __DEFAULT ->
725+-- let { wild_a2og = I# sc1_s3oS } in
726+-- main_$s$wgo1
727+-- sc_s3oT (+# sc1_s3oS 1#) (\ x_X9 -> fs2_a2lw (: wild_a2og x_X9));
728+
729+-- |
730+-- Definitions:
731+--
732+-- >>> toList = Stream.foldr (:) []
733+-- >>> toList = Stream.fold Fold.toList
734+--
735+-- Convert a stream into a list in the underlying monad. The list can be
736+-- consumed lazily in a lazy monad (e.g. 'Identity'). In a strict monad (e.g.
737+-- IO) the whole list is generated and buffered before it can be consumed.
738+--
739+-- /Warning!/ working on large lists accumulated as buffers in memory could be
740+-- very inefficient, consider using "Streamly.Data.Array" instead.
741+--
742+-- Note that this could a bit more efficient compared to @Stream.fold
743+-- Fold.toList@, and it can fuse with pure list consumers.
744+--
697745{-# INLINE_NORMAL toList #-}
698746toList :: Monad m => Stream m a -> m [a]
699747toList = Streamly.Internal.Data.Stream.StreamD.Type.foldr (:) []