iterate package:streamly

>>> iterate f x = x `Stream.cons` iterate f x
Generate an infinite stream with x as the first element and each successive element derived by applying the function f on the previous element.
>>> Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1
[1,2,3,4,5]
In an Either stream iterate on Lefts. This is a special case of iterateMapWith:
iterateMapLeftsWith combine f = iterateMapWith combine (either f (const nil))
To traverse a directory tree:
iterateMapLeftsWith serial Dir.toEither (fromPure (Left "tmp"))
Pre-release
Like iterateM but iterates after mapping a stream generator on the output. Yield an input element in the output stream, map a stream generator on it and then do the same on the resulting stream. This can be used for a depth first traversal of a tree like structure. Note that iterateM is a special case of iterateMapWith:
iterateM f = iterateMapWith serial (fromEffect . f) . fromEffect
It can be used to traverse a tree structure. For example, to list a directory tree:
Stream.iterateMapWith Stream.serial
(either Dir.toEither (const nil))
(fromPure (Left "tmp"))
Pre-release
Like iterateMap but carries a state in the stream generation function. This can be used to traverse graph like structures, we can remember the visited nodes in the state to avoid cycles. Note that a combination of iterateMap and usingState can also be used to traverse graphs. However, this function provides a more localized state instead of using a global state. See also: mfix Pre-release
Same as iterateMapWith Stream.serial but more efficient due to stream fusion. Unimplemented
>>> iterateM f m = m >>= \a -> return a `Stream.consM` iterateM f (f a)
Generate an infinite stream with the first element generated by the action m and each successive element derived by applying the monadic function f on the previous element.
>>> pr n = threadDelay 1000000 >> print n

>>> :{
Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
& Stream.take 3
& Stream.fromSerial
& Stream.toList
:}
0
1
[0,1,2]
When run concurrently, the next iteration can run concurrently with the processing of the previous iteration. Note that more than one iteration cannot run concurrently as the next iteration depends on the output of the previous iteration.
>>> :{
Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
& Stream.delay 1
& Stream.take 3
& Stream.fromAsync
& Stream.toList
:}
0
1
...
Concurrent Since: 0.1.2 Since: 0.7.0 (signature change)
Same as concatIterate but concurrent. Pre-release
Iterate a fold generator on a stream. The initial value b is used to generate the first fold, the fold is applied on the stream and the result of the fold is used to generate the next fold and so on.
>>> import Data.Monoid (Sum(..))
>>> f x = return (Fold.take 2 (Fold.sconcat x))
>>> s = Stream.map Sum $ Stream.fromList [1..10]
>>> Stream.toList $ Stream.map getSum $ Stream.foldIterateM f (pure 0) s
[3,10,21,36,55,55]
This is the streaming equivalent of monad like sequenced application of folds where next fold is dependent on the previous fold. Pre-release
Iterate a parser generating function on a stream. The initial value b is used to generate the first parser, the parser is applied on the stream and the result is used to generate the next parser and so on.
>>> import Data.Monoid (Sum(..))

>>> Stream.toList $ fmap getSum $ Stream.rights $ Stream.parseIterate (\b -> Parser.takeBetween 0 2 (Fold.sconcat b)) (Sum 0) $ fmap Sum $ Stream.fromList [1..10]
[3,10,21,36,55,55]
This is the streaming equivalent of monad like sequenced application of parsers where next parser is dependent on the previous parser. Pre-release
Like foldIterateM but using the Refold type instead. This could be much more efficient due to stream fusion. Internal