on master help sign in
Remove usage of `cons` from Data.Stream docs
dd0e41fHarendra Kumar
core/src/DocTestDataStreamK.hs+1
@@ -1,6 +1,7 @@
1{- $setup
1{- $setup
2
2
3>>> :m
3>>> :m
4+>>> import Control.Concurrent (threadDelay)
4>>> import Data.Function (fix, (&))
5>>> import Data.Function (fix, (&))
5>>> import Data.Semigroup (cycle1)
6>>> import Data.Semigroup (cycle1)
6
7
core/src/Streamly/Data/Stream.hs+5−5
@@ -49,11 +49,11 @@ module Streamly.Data.Stream
49 -- >>> fromFoldableM = Stream.sequence . fromFoldable
49 -- >>> fromFoldableM = Stream.sequence . fromFoldable
50
50
51 -- ** Primitives
51 -- ** Primitives
52− -- | Primitives to construct a stream from pure values or monadic actions.
52+ -- | A fused 'Stream' is never constructed using 'cons', we always convert
53− -- All other stream construction and generation combinators described later
53+ -- other type of containers like list into streams, or generate it using
54− -- can be expressed in terms of these primitives. However, the special
54+ -- custom functions provided in this module. The 'cons' primitive has a
55− -- versions provided in this module can be much more efficient in most
55+ -- rare use in fusing a small number of elements. On the other hand, it is
56− -- cases. Users can create custom combinators using these primitives.
56+ -- common to construct 'StreamK' stream using the 'StreamK.cons' primitive.
57 , nil
57 , nil
58 , nilM
58 , nilM
59 , cons
59 , cons
core/src/Streamly/Data/StreamK.hs+5
@@ -50,6 +50,11 @@ module Streamly.Data.StreamK
50
50
51 -- * Construction
51 -- * Construction
52 -- ** Primitives
52 -- ** Primitives
53+ -- | Primitives to construct a stream from pure values or monadic actions.
54+ -- All other stream construction and generation combinators described later
55+ -- can be expressed in terms of these primitives. However, the special
56+ -- versions provided in this module can be much more efficient in some
57+ -- cases. Users can create custom combinators using these primitives.
53 , nil
58 , nil
54 , nilM
59 , nilM
55 , cons
60 , cons
core/src/Streamly/Internal/Data/Stream/StreamD/Generate.hs+47−62
@@ -147,7 +147,7 @@ import Streamly.Internal.Data.Stream.StreamD.Type
147
147
148-- | A stream that terminates without producing any output or side effect.
148-- | A stream that terminates without producing any output or side effect.
149--
149--
150−-- >>> Stream.fold Fold.toList Stream.nil
150+-- >>> Stream.toList Stream.nil
151-- []
151-- []
152--
152--
153{-# INLINE_NORMAL nil #-}
153{-# INLINE_NORMAL nil #-}
@@ -157,21 +157,22 @@ nil = Stream (\_ _ -> pure Stop) ()
157-- XXX implement in terms of consM?
157-- XXX implement in terms of consM?
158-- cons x = consM (return x)
158-- cons x = consM (return x)
159
159
160+-- | WARNING! You almost always need StreamK.'Streamly.Data.StreamK.cons'
161+-- instead.
162+--
160−-- | Fuse a pure value at the head of an existing stream::
163+-- Fuse a pure value at the head of an existing stream::
161--
164--
162-- >>> s = 1 `Stream.cons` Stream.fromList [2,3]
165-- >>> s = 1 `Stream.cons` Stream.fromList [2,3]
163−-- >>> Stream.fold Fold.toList s
166+-- >>> Stream.toList s
164-- [1,2,3]
167-- [1,2,3]
165--
168--
166−-- This function should not be used to dynamically construct a stream. If a
169+-- From an implementation perspective, StreamK.cons translates into a
167−-- stream is constructed by successive use of this function it would take
170+-- functional call whereas fused cons translates into a conditional branch
168−-- O(n^2) time to consume the stream.
171+-- (jump). However, the overhead of the function call in StreamK.cons only
169−--
172+-- occurs once, while the overhead of the conditional branch in fused cons is
170−-- This function should only be used to statically fuse an element with a
173+-- incurred for each subsequent element in the stream. As a result,
171−-- stream. Do not use this recursively or where it cannot be inlined.
174+-- StreamK.cons has a time complexity of O(n), while fused cons has a time
172−--
175+-- complexity of O(n^2), where @n@ represents the number of 'cons' used.
173−-- See "Streamly.Data.StreamK" for a 'cons' that can be used to
174−-- construct a stream recursively.
175--
176--
176-- Definition:
177-- Definition:
177--
178--
@@ -205,7 +206,7 @@ cons x (Stream step state) = Stream step1 Nothing
205-- if b > 2
206-- if b > 2
206-- then return Nothing
207-- then return Nothing
207-- else return (Just (b, b + 1))
208-- else return (Just (b, b + 1))
208−-- in Stream.fold Fold.toList $ Stream.unfoldrM f 0
209+-- in Stream.toList $ Stream.unfoldrM f 0
209-- :}
210-- :}
210-- [0,1,2]
211-- [0,1,2]
211--
212--
@@ -224,15 +225,7 @@ unfoldrM next = Stream step
224 Nothing -> Stop
225 Nothing -> Stop
225#endif
226#endif
226
227
227−-- |
228−-- >>> :{
229−-- unfoldr step s =
230−-- case step s of
231−-- Nothing -> Stream.nil
232−-- Just (a, b) -> a `Stream.cons` unfoldr step b
233−-- :}
234−--
235−-- Build a stream by unfolding a /pure/ step function @step@ starting from a
228+-- | Build a stream by unfolding a /pure/ step function @step@ starting from a
236-- seed @s@. The step function returns the next element in the stream and the
229-- seed @s@. The step function returns the next element in the stream and the
237-- next seed value. When it is done it returns 'Nothing' and the stream ends.
230-- next seed value. When it is done it returns 'Nothing' and the stream ends.
238-- For example,
231-- For example,
@@ -242,7 +235,7 @@ unfoldrM next = Stream step
242-- if b > 2
235-- if b > 2
243-- then Nothing
236-- then Nothing
244-- else Just (b, b + 1)
237-- else Just (b, b + 1)
245−-- in Stream.fold Fold.toList $ Stream.unfoldr f 0
238+-- in Stream.toList $ Stream.unfoldr f 0
246-- :}
239-- :}
247-- [0,1,2]
240-- [0,1,2]
248--
241--
@@ -256,8 +249,6 @@ unfoldr f = unfoldrM (return . f)
256
249
257-- |
250-- |
258-- >>> repeatM = Stream.sequence . Stream.repeat
251-- >>> repeatM = Stream.sequence . Stream.repeat
259−-- >>> repeatM = fix . Stream.consM
260−-- >>> repeatM = cycle1 . Stream.fromEffect
261--
252--
262-- Generate a stream by repeatedly executing a monadic action forever.
253-- Generate a stream by repeatedly executing a monadic action forever.
263--
254--
@@ -420,10 +411,10 @@ enumerateFromThenToIntegralDn from next to = Stream step EnumInit
420-- first element is @from@, the second element is @then@ and the successive
411-- first element is @from@, the second element is @then@ and the successive
421-- elements are in increments of @then - from@ up to @to@.
412-- elements are in increments of @then - from@ up to @to@.
422--
413--
423−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToIntegral 0 2 6
414+-- >>> Stream.toList $ Stream.enumerateFromThenToIntegral 0 2 6
424-- [0,2,4,6]
415-- [0,2,4,6]
425--
416--
426−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToIntegral 0 (-2) (-6)
417+-- >>> Stream.toList $ Stream.enumerateFromThenToIntegral 0 (-2) (-6)
427-- [0,-2,-4,-6]
418-- [0,-2,-4,-6]
428--
419--
429{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
420{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
@@ -444,10 +435,10 @@ enumerateFromThenToIntegral from next to
444-- is @then@ and the successive elements are in increments of @then - from@.
435-- is @then@ and the successive elements are in increments of @then - from@.
445-- The stream is bounded by the size of the 'Integral' type.
436-- The stream is bounded by the size of the 'Integral' type.
446--
437--
447−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) 2
438+-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) 2
448-- [0,2,4,6]
439-- [0,2,4,6]
449--
440--
450−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) (-2)
441+-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) (-2)
451-- [0,-2,-4,-6]
442-- [0,-2,-4,-6]
452--
443--
453{-# INLINE_NORMAL enumerateFromThenIntegral #-}
444{-# INLINE_NORMAL enumerateFromThenIntegral #-}
@@ -471,10 +462,10 @@ enumerateFromThenIntegral from next =
471-- CAUTION: This function is not safe for finite integral types. It does not
462-- CAUTION: This function is not safe for finite integral types. It does not
472-- check for overflow, underflow or bounds.
463-- check for overflow, underflow or bounds.
473--
464--
474−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromStepIntegral 0 2
465+-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromStepIntegral 0 2
475-- [0,2,4,6]
466-- [0,2,4,6]
476--
467--
477−-- >>> Stream.fold Fold.toList $ Stream.take 3 $ Stream.enumerateFromStepIntegral 0 (-2)
468+-- >>> Stream.toList $ Stream.take 3 $ Stream.enumerateFromStepIntegral 0 (-2)
478-- [0,-2,-4]
469-- [0,-2,-4]
479--
470--
480{-# INLINE_NORMAL enumerateFromStepIntegral #-}
471{-# INLINE_NORMAL enumerateFromStepIntegral #-}
@@ -495,7 +486,7 @@ enumerateFromStepIntegral from stride =
495-- element is @from@ and successive elements are in increments of @1@ up to
486-- element is @from@ and successive elements are in increments of @1@ up to
496-- @to@.
487-- @to@.
497--
488--
498−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromToIntegral 0 4
489+-- >>> Stream.toList $ Stream.enumerateFromToIntegral 0 4
499-- [0,1,2,3,4]
490-- [0,1,2,3,4]
500--
491--
501{-# INLINE enumerateFromToIntegral #-}
492{-# INLINE enumerateFromToIntegral #-}
@@ -507,7 +498,7 @@ enumerateFromToIntegral from to =
507-- stream whose first element is @from@ and the successive elements are in
498-- stream whose first element is @from@ and the successive elements are in
508-- increments of @1@. The stream is bounded by the size of the 'Integral' type.
499-- increments of @1@. The stream is bounded by the size of the 'Integral' type.
509--
500--
510−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromIntegral (0 :: Int)
501+-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromIntegral (0 :: Int)
511-- [0,1,2,3]
502-- [0,1,2,3]
512--
503--
513{-# INLINE enumerateFromIntegral #-}
504{-# INLINE enumerateFromIntegral #-}
@@ -534,7 +525,7 @@ enumerateFromIntegral from = enumerateFromToIntegral from maxBound
534--
525--
535-- This is the equivalent to 'enumFrom' for 'Fractional' types. For example:
526-- This is the equivalent to 'enumFrom' for 'Fractional' types. For example:
536--
527--
537−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromFractional 1.1
528+-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromFractional 1.1
538-- [1.1,2.1,3.1,4.1]
529-- [1.1,2.1,3.1,4.1]
539--
530--
540{-# INLINE enumerateFromFractional #-}
531{-# INLINE enumerateFromFractional #-}
@@ -550,10 +541,10 @@ enumerateFromFractional = enumerateFromNum
550-- This is the equivalent of 'enumFromThen' for 'Fractional' types. For
541-- This is the equivalent of 'enumFromThen' for 'Fractional' types. For
551-- example:
542-- example:
552--
543--
553−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 2.1
544+-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 2.1
554-- [1.1,2.1,3.1,4.1]
545-- [1.1,2.1,3.1,4.1]
555--
546--
556−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 (-2.1)
547+-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 (-2.1)
557-- [1.1,-2.1,-5.300000000000001,-8.500000000000002]
548-- [1.1,-2.1,-5.300000000000001,-8.500000000000002]
558--
549--
559{-# INLINE enumerateFromThenFractional #-}
550{-# INLINE enumerateFromThenFractional #-}
@@ -570,10 +561,10 @@ enumerateFromThenFractional = enumerateFromThenNum
570-- This is the equivalent of 'enumFromTo' for 'Fractional' types. For
561-- This is the equivalent of 'enumFromTo' for 'Fractional' types. For
571-- example:
562-- example:
572--
563--
573−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromToFractional 1.1 4
564+-- >>> Stream.toList $ Stream.enumerateFromToFractional 1.1 4
574-- [1.1,2.1,3.1,4.1]
565-- [1.1,2.1,3.1,4.1]
575--
566--
576−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromToFractional 1.1 4.6
567+-- >>> Stream.toList $ Stream.enumerateFromToFractional 1.1 4.6
577-- [1.1,2.1,3.1,4.1,5.1]
568-- [1.1,2.1,3.1,4.1,5.1]
578--
569--
579-- Notice that the last element is equal to the specified @to@ value after
570-- Notice that the last element is equal to the specified @to@ value after
@@ -594,10 +585,10 @@ enumerateFromToFractional from to =
594-- This is the equivalent of 'enumFromThenTo' for 'Fractional' types. For
585-- This is the equivalent of 'enumFromThenTo' for 'Fractional' types. For
595-- example:
586-- example:
596--
587--
597−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToFractional 0.1 2 6
588+-- >>> Stream.toList $ Stream.enumerateFromThenToFractional 0.1 2 6
598-- [0.1,2.0,3.9,5.799999999999999]
589-- [0.1,2.0,3.9,5.799999999999999]
599--
590--
600−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToFractional 0.1 (-2) (-6)
591+-- >>> Stream.toList $ Stream.enumerateFromThenToFractional 0.1 (-2) (-6)
601-- [0.1,-2.0,-4.1000000000000005,-6.200000000000001]
592-- [0.1,-2.0,-4.1000000000000005,-6.200000000000001]
602--
593--
603{-# INLINE_NORMAL enumerateFromThenToFractional #-}
594{-# INLINE_NORMAL enumerateFromThenToFractional #-}
@@ -672,13 +663,13 @@ class Enum a => Enumerable a where
672 -- @from@, enumerating up to 'maxBound' when the type is 'Bounded' or
663 -- @from@, enumerating up to 'maxBound' when the type is 'Bounded' or
673 -- generating an infinite stream when the type is not 'Bounded'.
664 -- generating an infinite stream when the type is not 'Bounded'.
674 --
665 --
675− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)
666+ -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)
676 -- [0,1,2,3]
667 -- [0,1,2,3]
677 --
668 --
678 -- For 'Fractional' types, enumeration is numerically stable. However, no
669 -- For 'Fractional' types, enumeration is numerically stable. However, no
679 -- overflow or underflow checks are performed.
670 -- overflow or underflow checks are performed.
680 --
671 --
681− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1
672+ -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1
682 -- [1.1,2.1,3.1,4.1]
673 -- [1.1,2.1,3.1,4.1]
683 --
674 --
684 enumerateFrom :: (Monad m) => a -> Stream m a
675 enumerateFrom :: (Monad m) => a -> Stream m a
@@ -687,16 +678,16 @@ class Enum a => Enumerable a where
687 -- the type up to the value @to@. If @to@ is smaller than @from@ then an
678 -- the type up to the value @to@. If @to@ is smaller than @from@ then an
688 -- empty stream is returned.
679 -- empty stream is returned.
689 --
680 --
690− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromTo 0 4
681+ -- >>> Stream.toList $ Stream.enumerateFromTo 0 4
691 -- [0,1,2,3,4]
682 -- [0,1,2,3,4]
692 --
683 --
693 -- For 'Fractional' types, the last element is equal to the specified @to@
684 -- For 'Fractional' types, the last element is equal to the specified @to@
694 -- value after rounding to the nearest integral value.
685 -- value after rounding to the nearest integral value.
695 --
686 --
696− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromTo 1.1 4
687+ -- >>> Stream.toList $ Stream.enumerateFromTo 1.1 4
697 -- [1.1,2.1,3.1,4.1]
688 -- [1.1,2.1,3.1,4.1]
698 --
689 --
699− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromTo 1.1 4.6
690+ -- >>> Stream.toList $ Stream.enumerateFromTo 1.1 4.6
700 -- [1.1,2.1,3.1,4.1,5.1]
691 -- [1.1,2.1,3.1,4.1,5.1]
701 --
692 --
702 enumerateFromTo :: (Monad m) => a -> a -> Stream m a
693 enumerateFromTo :: (Monad m) => a -> a -> Stream m a
@@ -708,10 +699,10 @@ class Enum a => Enumerable a where
708 -- 'Bounded' types the stream ends when 'maxBound' is reached, for
699 -- 'Bounded' types the stream ends when 'maxBound' is reached, for
709 -- unbounded types it keeps enumerating infinitely.
700 -- unbounded types it keeps enumerating infinitely.
710 --
701 --
711− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2
702+ -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2
712 -- [0,2,4,6]
703 -- [0,2,4,6]
713 --
704 --
714− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)
705+ -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)
715 -- [0,-2,-4,-6]
706 -- [0,-2,-4,-6]
716 --
707 --
717 enumerateFromThen :: (Monad m) => a -> a -> Stream m a
708 enumerateFromThen :: (Monad m) => a -> a -> Stream m a
@@ -722,10 +713,10 @@ class Enum a => Enumerable a where
722 -- occur downwards or upwards depending on whether @then@ comes before or
713 -- occur downwards or upwards depending on whether @then@ comes before or
723 -- after @from@.
714 -- after @from@.
724 --
715 --
725− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenTo 0 2 6
716+ -- >>> Stream.toList $ Stream.enumerateFromThenTo 0 2 6
726 -- [0,2,4,6]
717 -- [0,2,4,6]
727 --
718 --
728− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)
719+ -- >>> Stream.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)
729 -- [0,-2,-4,-6]
720 -- [0,-2,-4,-6]
730 --
721 --
731 enumerateFromThenTo :: (Monad m) => a -> a -> a -> Stream m a
722 enumerateFromThenTo :: (Monad m) => a -> a -> a -> Stream m a
@@ -1075,17 +1066,14 @@ generate n gen = generateM n (return . gen)
1075-- Iteration
1066-- Iteration
1076-------------------------------------------------------------------------------
1067-------------------------------------------------------------------------------
1077
1068
1078−-- |
1079−-- >>> iterateM f m = m >>= \a -> return a `Stream.consM` iterateM f (f a)
1080−--
1081−-- Generate an infinite stream with the first element generated by the action
1069+-- | Generate an infinite stream with the first element generated by the action
1082−-- @m@ and each successive element derived by applying the monadic function
1070+-- @m@ and each successive element derived by applying the monadic function @f@
1083−-- @f@ on the previous element.
1071+-- on the previous element.
1084--
1072--
1085-- >>> :{
1073-- >>> :{
1086-- Stream.iterateM (\x -> print x >> return (x + 1)) (return 0)
1074-- Stream.iterateM (\x -> print x >> return (x + 1)) (return 0)
1087-- & Stream.take 3
1075-- & Stream.take 3
1088−-- & Stream.fold Fold.toList
1076+-- & Stream.toList
1089-- :}
1077-- :}
1090-- 0
1078-- 0
1091-- 1
1079-- 1
@@ -1099,14 +1087,11 @@ iterateM step = unfold (Unfold.iterateM step)
1099iterateM step = Stream (\_ st -> st >>= \(!x) -> return $ Yield x (step x))
1087iterateM step = Stream (\_ st -> st >>= \(!x) -> return $ Yield x (step x))
1100#endif
1088#endif
1101
1089
1102−-- |
1103−-- >>> iterate f x = x `Stream.cons` iterate f x
1104−--
1105−-- Generate an infinite stream with @x@ as the first element and each
1090+-- | Generate an infinite stream with @x@ as the first element and each
1106-- successive element derived by applying the function @f@ on the previous
1091-- successive element derived by applying the function @f@ on the previous
1107-- element.
1092-- element.
1108--
1093--
1109−-- >>> Stream.fold Fold.toList $ Stream.take 5 $ Stream.iterate (+1) 1
1094+-- >>> Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1
1110-- [1,2,3,4,5]
1095-- [1,2,3,4,5]
1111--
1096--
1112{-# INLINE_NORMAL iterate #-}
1097{-# INLINE_NORMAL iterate #-}
@@ -1196,7 +1181,7 @@ fromPtrN n = take n . fromPtr
1196-- Note that this is completely safe when reading from Haskell string
1181-- Note that this is completely safe when reading from Haskell string
1197-- literals because they are guaranteed to be NULL terminated:
1182-- literals because they are guaranteed to be NULL terminated:
1198--
1183--
1199−-- >>> Stream.fold Fold.toList $ Stream.fromByteStr# "\1\2\3\0"#
1184+-- >>> Stream.toList $ Stream.fromByteStr# "\1\2\3\0"#
1200-- [1,2,3]
1185-- [1,2,3]
1201--
1186--
1202{-# INLINE fromByteStr# #-}
1187{-# INLINE fromByteStr# #-}
core/src/Streamly/Internal/Data/Stream/StreamK.hs+40
@@ -255,6 +255,20 @@ unfoldrA = undefined
255-- Special generation
255-- Special generation
256-------------------------------------------------------------------------------
256-------------------------------------------------------------------------------
257
257
258+-- |
259+-- >>> repeatM = StreamK.sequence . StreamK.repeat
260+-- >>> repeatM = fix . StreamK.consM
261+-- >>> repeatM = cycle1 . StreamK.fromEffect
262+--
263+-- Generate a stream by repeatedly executing a monadic action forever.
264+--
265+-- >>> :{
266+-- repeatAction =
267+-- StreamK.repeatM (threadDelay 1000000 >> print 1)
268+-- & StreamK.take 10
269+-- & StreamK.fold Fold.drain
270+-- :}
271+--
258repeatM :: Monad m => m a -> StreamK m a
272repeatM :: Monad m => m a -> StreamK m a
259repeatM = repeatMWith consM
273repeatM = repeatMWith consM
260
274
@@ -276,12 +290,38 @@ fromIndices gen = go 0
276 where
290 where
277 go n = gen n `cons` go (n + 1)
291 go n = gen n `cons` go (n + 1)
278
292
293+-- |
294+-- >>> iterate f x = x `StreamK.cons` iterate f x
295+--
296+-- Generate an infinite stream with @x@ as the first element and each
297+-- successive element derived by applying the function @f@ on the previous
298+-- element.
299+--
300+-- >>> StreamK.toList $ StreamK.take 5 $ StreamK.iterate (+1) 1
301+-- [1,2,3,4,5]
302+--
279{-# INLINE iterate #-}
303{-# INLINE iterate #-}
280iterate :: (a -> a) -> a -> StreamK m a
304iterate :: (a -> a) -> a -> StreamK m a
281iterate step = go
305iterate step = go
282 where
306 where
283 go !s = cons s (go (step s))
307 go !s = cons s (go (step s))
284
308
309+-- |
310+-- >>> iterateM f m = m >>= \a -> return a `StreamK.consM` iterateM f (f a)
311+--
312+-- Generate an infinite stream with the first element generated by the action
313+-- @m@ and each successive element derived by applying the monadic function
314+-- @f@ on the previous element.
315+--
316+-- >>> :{
317+-- StreamK.iterateM (\x -> print x >> return (x + 1)) (return 0)
318+-- & StreamK.take 3
319+-- & StreamK.toList
320+-- :}
321+-- 0
322+-- 1
323+-- [0,1,2]
324+--
285{-# INLINE iterateM #-}
325{-# INLINE iterateM #-}
286iterateM :: Monad m => (a -> m a) -> m a -> StreamK m a
326iterateM :: Monad m => (a -> m a) -> m a -> StreamK m a
287iterateM = iterateMWith consM
327iterateM = iterateMWith consM
core/src/Streamly/Internal/Data/Stream/StreamK/Type.hs+36
@@ -1688,6 +1688,28 @@ interleaveMin m1 m2 = mkStream $ \st yld _ stp -> do
1688-- Generation
1688-- Generation
1689-------------------------------------------------------------------------------
1689-------------------------------------------------------------------------------
1690
1690
1691+-- |
1692+-- >>> :{
1693+-- unfoldr step s =
1694+-- case step s of
1695+-- Nothing -> StreamK.nil
1696+-- Just (a, b) -> a `StreamK.cons` unfoldr step b
1697+-- :}
1698+--
1699+-- Build a stream by unfolding a /pure/ step function @step@ starting from a
1700+-- seed @s@. The step function returns the next element in the stream and the
1701+-- next seed value. When it is done it returns 'Nothing' and the stream ends.
1702+-- For example,
1703+--
1704+-- >>> :{
1705+-- let f b =
1706+-- if b > 2
1707+-- then Nothing
1708+-- else Just (b, b + 1)
1709+-- in StreamK.toList $ StreamK.unfoldr f 0
1710+-- :}
1711+-- [0,1,2]
1712+--
1691{-# INLINE unfoldr #-}
1713{-# INLINE unfoldr #-}
1692unfoldr :: (b -> Maybe (a, b)) -> b -> StreamK m a
1714unfoldr :: (b -> Maybe (a, b)) -> b -> StreamK m a
1693unfoldr next s0 = build $ \yld stp ->
1715unfoldr next s0 = build $ \yld stp ->
@@ -1713,6 +1735,20 @@ unfoldrMWith cns step = go
1713 Just (a, b) -> yld a (go b)
1735 Just (a, b) -> yld a (go b)
1714 Nothing -> stp
1736 Nothing -> stp
1715
1737
1738+-- | Build a stream by unfolding a /monadic/ step function starting from a
1739+-- seed. The step function returns the next element in the stream and the next
1740+-- seed value. When it is done it returns 'Nothing' and the stream ends. For
1741+-- example,
1742+--
1743+-- >>> :{
1744+-- let f b =
1745+-- if b > 2
1746+-- then return Nothing
1747+-- else return (Just (b, b + 1))
1748+-- in StreamK.toList $ StreamK.unfoldrM f 0
1749+-- :}
1750+-- [0,1,2]
1751+--
1716{-# INLINE unfoldrM #-}
1752{-# INLINE unfoldrM #-}
1717unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> StreamK m a
1753unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> StreamK m a
1718unfoldrM = unfoldrMWith consM
1754unfoldrM = unfoldrMWith consM