on master help sign in
Update doctests of the Generate module
8f03957Harendra Kumar
src/Streamly/Internal/Data/Stream/IsStream/Generate.hs+87−74
@@ -125,11 +125,15 @@ import Prelude hiding (iterate, replicate, repeat)
125
125
126-- $setup
126-- $setup
127-- >>> :m
127-- >>> :m
128+-- >>> import Data.Function ((&))
128-- >>> import Prelude hiding (iterate, replicate, repeat)
129-- >>> import Prelude hiding (iterate, replicate, repeat)
129-- >>> import qualified Streamly.Prelude as Stream
130-- >>> import qualified Streamly.Prelude as Stream
130-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream
131-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream
131-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
132-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
132-- >>> import Control.Concurrent (threadDelay)
133-- >>> import Control.Concurrent (threadDelay)
134+-- >>> import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
135+--
136+-- >>> hSetBuffering stdout LineBuffering
133
137
134------------------------------------------------------------------------------
138------------------------------------------------------------------------------
135-- From Unfold
139-- From Unfold
@@ -159,29 +163,26 @@ unfold0 unf = unfold unf (error "unfold0: unexpected void evaluation")
159------------------------------------------------------------------------------
163------------------------------------------------------------------------------
160
164
161-- |
165-- |
162−-- @
166+-- >>> :{
163-- unfoldr step s =
167-- unfoldr step s =
164-- case step s of
168-- case step s of
165−-- Nothing -> 'K.nil'
169+-- Nothing -> Stream.nil
166−-- Just (a, b) -> a \`cons` unfoldr step b
170+-- Just (a, b) -> a `Stream.cons` unfoldr step b
167−-- @
171+-- :}
168--
172--
169-- Build a stream by unfolding a /pure/ step function @step@ starting from a
173-- Build a stream by unfolding a /pure/ step function @step@ starting from a
170-- seed @s@. The step function returns the next element in the stream and the
174-- seed @s@. The step function returns the next element in the stream and the
171-- next seed value. When it is done it returns 'Nothing' and the stream ends.
175-- next seed value. When it is done it returns 'Nothing' and the stream ends.
172-- For example,
176-- For example,
173--
177--
174−-- @
175-- >>> :{
178-- >>> :{
176-- let f b =
179-- let f b =
177−-- if b > 3
180+-- if b > 2
178-- then Nothing
181-- then Nothing
179-- else Just (b, b + 1)
182-- else Just (b, b + 1)
180-- in Stream.toList $ Stream.unfoldr f 0
183-- in Stream.toList $ Stream.unfoldr f 0
181-- :}
184-- :}
182−-- [0,1,2,3]
185+-- [0,1,2]
183−--
184−-- @
185--
186--
186-- @since 0.1.0
187-- @since 0.1.0
187{-# INLINE_EARLY unfoldr #-}
188{-# INLINE_EARLY unfoldr #-}
@@ -195,26 +196,28 @@ unfoldr step seed = fromStreamS (S.unfoldr step seed)
195-- seed value. When it is done it returns 'Nothing' and the stream ends. For
196-- seed value. When it is done it returns 'Nothing' and the stream ends. For
196-- example,
197-- example,
197--
198--
198−-- @
199-- >>> :{
199-- >>> :{
200-- let f b =
200-- let f b =
201−-- if b > 3
201+-- if b > 2
202-- then return Nothing
202-- then return Nothing
203-- else return (Just (b, b + 1))
203-- else return (Just (b, b + 1))
204-- in Stream.toList $ Stream.unfoldrM f 0
204-- in Stream.toList $ Stream.unfoldrM f 0
205-- :}
205-- :}
206−-- [0,1,2,3]
206+-- [0,1,2]
207--
207--
208−-- @
209-- When run concurrently, the next unfold step can run concurrently with the
208-- When run concurrently, the next unfold step can run concurrently with the
210-- processing of the output of the previous step. Note that more than one step
209-- processing of the output of the previous step. Note that more than one step
211-- cannot run concurrently as the next step depends on the output of the
210-- cannot run concurrently as the next step depends on the output of the
212-- previous step.
211-- previous step.
213--
212--
214−-- @
213+-- >>> :{
215−-- (fromAsync $ S.unfoldrM (\\n -> liftIO (threadDelay 1000000) >> return (Just (n, n + 1))) 0)
214+-- let f b =
216−-- & S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
215+-- if b > 2
217−-- @
216+-- then return Nothing
217+-- else threadDelay 1000000 >> return (Just (b, b + 1))
218+-- in Stream.toList $ Stream.delay 1 $ Stream.fromAsync $ Stream.unfoldrM f 0
219+-- :}
220+-- [0,1,2]
218--
221--
219-- /Concurrent/
222-- /Concurrent/
220--
223--
@@ -253,9 +256,7 @@ repeat :: (IsStream t, Monad m) => a -> t m a
253repeat = fromStreamS . S.repeat
256repeat = fromStreamS . S.repeat
254
257
255-- |
258-- |
256−-- @
257−-- replicate = take n . repeat
259+-- >>> replicate n = Stream.take n . Stream.repeat
258−-- @
259--
260--
260-- Generate a stream of length @n@ by repeating a value @n@ times.
261-- Generate a stream of length @n@ by repeating a value @n@ times.
261--
262--
@@ -265,16 +266,25 @@ replicate :: (IsStream t, Monad m) => Int -> a -> t m a
265replicate n = fromStreamS . S.replicate n
266replicate n = fromStreamS . S.replicate n
266
267
267-- |
268-- |
268−-- @
269−-- replicateM = take n . repeatM
269+-- >>> replicateM n = Stream.take n . Stream.repeatM
270−-- @
271--
270--
272-- Generate a stream by performing a monadic action @n@ times. Same as:
271-- Generate a stream by performing a monadic action @n@ times. Same as:
273--
272--
274−-- @
273+-- >>> pr n = threadDelay 1000000 >> print n
274+--
275+-- This runs serially and takes 3 seconds:
276+--
275−-- drain $ fromSerial $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
277+-- >>> Stream.drain $ Stream.fromSerial $ Stream.replicateM 3 $ pr 1
278+-- 1
279+-- 1
280+-- 1
281+--
282+-- This runs concurrently and takes just 1 second:
283+--
276−-- drain $ fromAsync $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
284+-- >>> Stream.drain $ Stream.fromAsync $ Stream.replicateM 3 $ pr 1
285+-- 1
286+-- 1
277−-- @
287+-- 1
278--
288--
279-- /Concurrent/
289-- /Concurrent/
280--
290--
@@ -398,10 +408,8 @@ timeout = undefined
398-- map. Check performance equivalence.
408-- map. Check performance equivalence.
399--
409--
400-- |
410-- |
401−-- @
402−-- fromIndices f = fmap f $ Stream.enumerateFrom 0
411+-- >>> fromIndices f = fmap f $ Stream.enumerateFrom 0
403−-- fromIndices f = let g i = f i \`cons` g (i + 1) in g 0
412+-- >>> fromIndices f = let g i = f i `Stream.cons` g (i + 1) in g 0
404−-- @
405--
413--
406-- Generate an infinite stream, whose values are the output of a function @f@
414-- Generate an infinite stream, whose values are the output of a function @f@
407-- applied on the corresponding index. Index starts at 0.
415-- applied on the corresponding index. Index starts at 0.
@@ -416,10 +424,8 @@ fromIndices = fromStreamS . S.fromIndices
416
424
417--
425--
418-- |
426-- |
419−-- @
420−-- fromIndicesM f = Stream.mapM f $ Stream.enumerateFrom 0
427+-- >>> fromIndicesM f = Stream.mapM f $ Stream.enumerateFrom 0
421−-- fromIndicesM f = let g i = f i \`consM` g (i + 1) in g 0
428+-- >>> fromIndicesM f = let g i = f i `Stream.consM` g (i + 1) in g 0
422−-- @
423--
429--
424-- Generate an infinite stream, whose values are the output of a monadic
430-- Generate an infinite stream, whose values are the output of a monadic
425-- function @f@ applied on the corresponding index. Index starts at 0.
431-- function @f@ applied on the corresponding index. Index starts at 0.
@@ -442,46 +448,54 @@ fromIndicesMSerial = fromStreamS . S.fromIndicesM
442------------------------------------------------------------------------------
448------------------------------------------------------------------------------
443
449
444-- |
450-- |
445−-- @
446−-- iterate f x = x \`cons` iterate f x
451+-- >>> iterate f x = x `Stream.cons` iterate f x
447−-- @
448--
452--
449-- Generate an infinite stream with @x@ as the first element and each
453-- Generate an infinite stream with @x@ as the first element and each
450-- successive element derived by applying the function @f@ on the previous
454-- successive element derived by applying the function @f@ on the previous
451-- element.
455-- element.
452--
456--
453−-- @
454-- >>> Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1
457-- >>> Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1
455-- [1,2,3,4,5]
458-- [1,2,3,4,5]
456--
459--
457−-- @
458−--
459-- @since 0.1.2
460-- @since 0.1.2
460{-# INLINE_NORMAL iterate #-}
461{-# INLINE_NORMAL iterate #-}
461iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a
462iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a
462iterate step = fromStreamS . S.iterate step
463iterate step = fromStreamS . S.iterate step
463
464
464-- |
465-- |
465−-- @
466−-- iterateM f m = m >>= \a -> return a \`consM` iterateM f (f a)
466+-- >>> iterateM f m = m >>= \a -> return a `Stream.consM` iterateM f (f a)
467−-- @
468--
467--
469-- Generate an infinite stream with the first element generated by the action
468-- Generate an infinite stream with the first element generated by the action
470-- @m@ and each successive element derived by applying the monadic function
469-- @m@ and each successive element derived by applying the monadic function
471-- @f@ on the previous element.
470-- @f@ on the previous element.
472--
471--
472+-- >>> pr n = threadDelay 1000000 >> print n
473+-- >>> :{
474+-- Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
475+-- & Stream.take 3
476+-- & Stream.fromSerial
477+-- & Stream.toList
478+-- :}
479+-- 0
480+-- 1
481+-- [0,1,2]
482+--
473-- When run concurrently, the next iteration can run concurrently with the
483-- When run concurrently, the next iteration can run concurrently with the
474-- processing of the previous iteration. Note that more than one iteration
484-- processing of the previous iteration. Note that more than one iteration
475-- cannot run concurrently as the next iteration depends on the output of the
485-- cannot run concurrently as the next iteration depends on the output of the
476-- previous iteration.
486-- previous iteration.
477--
487--
478−-- @
488+-- >>> :{
479−-- drain $ fromSerial $ S.take 10 $ S.iterateM
480−-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
489+-- Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
481−--
490+-- & Stream.delay 1
491+-- & Stream.take 3
482−-- drain $ fromAsync $ S.take 10 $ S.iterateM
492+-- & Stream.fromAsync
483−-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
493+-- & Stream.toList
484−-- @
494+-- :}
495+-- 0
496+-- 1
497+-- 2
498+-- [0,1,2]
485--
499--
486-- /Concurrent/
500-- /Concurrent/
487--
501--
@@ -505,13 +519,12 @@ iterateMSerial step = fromStreamS . S.iterateM step
505--
519--
506-- The function @fix@ defined as:
520-- The function @fix@ defined as:
507--
521--
508−-- > fix f = let x = f x in x
522+-- >>> fix f = let x = f x in x
509--
523--
510-- ensures that the argument of a function and its output refer to the same
524-- ensures that the argument of a function and its output refer to the same
511-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
525-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
512-- in terms of itself, creating structures with cyclic references.
526-- in terms of itself, creating structures with cyclic references.
513--
527--
514−-- >>> import Data.Function (fix)
515-- >>> f ~(a, b) = ([1, b], head a)
528-- >>> f ~(a, b) = ([1, b], head a)
516-- >>> fix f
529-- >>> fix f
517-- ([1,1],1)
530-- ([1,1],1)
@@ -529,21 +542,18 @@ iterateMSerial step = fromStreamS . S.iterateM step
529-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
542-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
530-- the first element of the tuple in terms of the second.
543-- the first element of the tuple in terms of the second.
531--
544--
532−-- @
533−-- import Streamly.Internal.Data.Stream.IsStream as Stream
545+-- >>> import Streamly.Internal.Data.Stream.IsStream as Stream
534−-- import System.IO.Unsafe (unsafeInterleaveIO)
546+-- >>> import System.IO.Unsafe (unsafeInterleaveIO)
535−--
536−-- main = do
537−-- Stream.mapM_ print $ Stream.mfix f
538--
547--
548+-- >>> :{
549+-- main = Stream.mapM_ print $ Stream.mfix f
539-- where
550-- where
540−--
541-- f action = do
551-- f action = do
542-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
552-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
543-- x <- Stream.fromListM [incr 1 action, incr 2 action]
553-- x <- Stream.fromListM [incr 1 action, incr 2 action]
544-- y <- Stream.fromList [4,5]
554-- y <- Stream.fromList [4,5]
545-- return (x, y)
555-- return (x, y)
546−-- @
556+-- :}
547--
557--
548-- Note: you cannot achieve this by just changing the order of the monad
558-- Note: you cannot achieve this by just changing the order of the monad
549-- statements because that would change the order in which the stream elements
559-- statements because that would change the order in which the stream elements
@@ -562,9 +572,7 @@ mfix f = fromStream $ K.mfix (toStream . f)
562------------------------------------------------------------------------------
572------------------------------------------------------------------------------
563
573
564-- |
574-- |
565−-- @
566−-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
575+-- >>> fromFoldable = Prelude.foldr Stream.cons Stream.nil
567−-- @
568--
576--
569-- Construct a stream from a 'Foldable' containing pure values:
577-- Construct a stream from a 'Foldable' containing pure values:
570--
578--
@@ -574,16 +582,20 @@ fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
574fromFoldable = fromStream . K.fromFoldable
582fromFoldable = fromStream . K.fromFoldable
575
583
576-- |
584-- |
577−-- @
578−-- fromFoldableM = 'Prelude.foldr' 'consM' 'K.nil'
585+-- >>> fromFoldableM = Prelude.foldr Stream.consM Stream.nil
579−-- @
580--
586--
581-- Construct a stream from a 'Foldable' containing monadic actions.
587-- Construct a stream from a 'Foldable' containing monadic actions.
582--
588--
583−-- @
589+-- >>> pr n = threadDelay 1000000 >> print n
584−-- drain $ fromSerial $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
590+-- >>> Stream.drain $ Stream.fromSerial $ Stream.fromFoldableM $ map pr [1,2,3]
591+-- 1
592+-- 2
593+-- 3
594+--
585−-- drain $ fromAsync $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
595+-- >>> Stream.drain $ Stream.fromAsync $ Stream.fromFoldableM $ map pr [1,2,3]
596+-- ...
597+-- ...
586−-- @
598+-- ...
587--
599--
588-- /Concurrent (do not use with 'fromParallel' on infinite containers)/
600-- /Concurrent (do not use with 'fromParallel' on infinite containers)/
589--
601--
@@ -593,9 +605,10 @@ fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
593fromFoldableM = Prelude.foldr consM IsStream.nil
605fromFoldableM = Prelude.foldr consM IsStream.nil
594
606
595-- |
607-- |
596−-- @
608+-- >>> fromListM = Stream.fromFoldableM
609+-- >>> fromListM = Stream.sequence . Stream.fromList
610+-- >>> fromListM = Stream.mapM id . Stream.fromList
597−-- fromListM = 'Prelude.foldr' 'K.consM' 'K.nil'
611+-- >>> fromListM = Prelude.foldr Stream.consM Stream.nil
598−-- @
599--
612--
600-- Construct a stream from a list of monadic actions. This is more efficient
613-- Construct a stream from a list of monadic actions. This is more efficient
601-- than 'fromFoldableM' for serial streams.
614-- than 'fromFoldableM' for serial streams.