HORIZON HASKELLDocslts/ghc-10.0.xfc4e5982026-10-11Search names, modules, packages, or :: a typeCtrl K

GHC 10.0.0.20260917 · lts/ghc-10.0.x · fc4e598 · 2026-10-11

Modulestreamly-core-0.3.1Haskell2010

Streamly.Internal.Data.Stream

Direct style re-implementation of CPS stream in Streamly.Internal.Data.StreamK. GHC is able to INLINE and fuse direct style better, providing better performance than CPS implementation.

import qualified Streamly.Internal.Data.Stream as Stream
  • 11 types
  • 1 class
  • 394 values
valueappend :: Monad m => Stream m a -> Stream m a -> Stream m a
#

WARNING! O(n^2) time complexity wrt number of streams. Suitable for statically fusing a small number of streams. Use the O(n) complexity StreamK.Streamly.Data.StreamK.append otherwise.

Fuses two streams sequentially, yielding all elements from the first stream, and then all elements from the second stream.

Example3 expressions
s1 = Stream.fromList [1,2]s2 = Stream.fromList [3,4]Stream.fold Fold.toList $ s1 `Stream.append` s2[1,2,3,4]
valuebfsConcatIterate
  1. :: Monad m
  2. => a -> Maybe (Stream m a)
  3. -> Stream m a
  4. -> Stream m a
#

Similar to concatIterate except that it traverses the stream in breadth first style (BFS). First, all the elements in the input stream are emitted, and then their traversals are emitted.

Example, list a directory tree using BFS:

Example3 expressions
f = either (Just . Dir.readEitherPaths id) (const Nothing)input = Stream.fromEffect (Left <$> Path.fromString ".")ls = Stream.bfsConcatIterate f input

Pre-release

valuebfsFoldIterate :: Fold m a (Either a a) -> Stream m a -> m (Maybe a)
#

N-Ary BFS style iterative fold, if the input stream finished before the fold then it returns Left otherwise Right. If the fold returns Left we terminate.

Unimplemented

valuebfsReduceIterate :: Monad m => (a -> a -> m a) -> Stream m a -> m (Maybe a)
#

Binary BFS style reduce, folds a level entirely using the supplied fold function, collecting the outputs as next level of the tree, then repeats the same process on the next level. The last elements of a previously folded level are folded first.

valueconcat :: Monad m => Stream m (Stream m a) -> Stream m a
#

Flatten a stream of streams to a single stream.

Example1 expression
concat = Stream.concatMap id

Pre-release

valueconcatEffect :: Monad m => m (Stream m a) -> Stream m a
#

Flatten a stream generated by an effect i.e. concat the effect monad with the stream monad.

Example2 expressions
concatEffect = Stream.concat . Stream.fromEffectconcatEffect eff = Stream.concatMapM (\() -> eff) (Stream.fromPure ())

See also: concat, sequence

valueconcatFor :: Monad m => Stream m a -> (a -> Stream m b) -> Stream m b
#

Map a stream generating function on each element of a stream and concatenate the results. This is the same as the bind function of the monad instance. It is just a flipped concatMap but more convenient to use for nested use case, feels like an imperative for loop. It is in fact equivalent to concat . for.

Example1 expression
concatFor = flip Stream.concatMap

A concatenating for loop:

Example1 expression
:{Stream.toList $    Stream.concatFor (Stream.fromList [1,2,3]) $ \x ->      Stream.fromPure x:}[1,2,3]

Use unfoldEach instead of concatFor where possible, unfoldEach is much faster due to fusion.

Nested concatenating for loops:

Example1 expression
:{Stream.toList $    Stream.concatFor (Stream.fromList [1,2,3]) $ \x ->     Stream.concatFor (Stream.fromList [4,5,6]) $ \y ->      Stream.fromPure (x, y):}[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]

If total iterations are kept the same, each increase in the nesting level increases the cost by roughly 2 times.

For significantly faster multi-level nesting, prefer using the better fusible, applicative-like crossWith over concatFor where possible.

concatFor is monad-like: it allows expressing dependencies between the outer and the inner loops of the nesting, it means that the stream generated by the inner loop is dynamically governed by the outer loop. This expressive power comes at a significant performance cost.

NOTE: We recommend using unfoldEach or unfoldCross instead of concatFor especially in performance critical code. unfoldEach is much faster than concatFor and matches its expressive power in terms of generating dependent inner streams, there is one important distinction though: the nesting structure when using unfoldEach is fixed statically in the code. In contrast, concatFor allows dynamic and arbitrary nesting through monadic composition. This means that deeply nested or programmatically determined levels of nesting are easier to express and compose with concatFor, though often at the cost of performance and fusion.

valueconcatForM :: Monad m => Stream m a -> (a -> m (Stream m b)) -> Stream m b
#

Like concatFor but maps an effectful function. It allows conveniently mixing monadic effects with streams.

Example2 expressions
import Control.Monad.IO.Class (liftIO):{Stream.toList $    Stream.concatForM (Stream.fromList [1,2,3]) $ \x -> do      liftIO $ putStrLn (show x)      pure $ Stream.fromPure x:}123[1,2,3]

Nested concatentating for loops:

Example1 expression
:{Stream.toList $    Stream.concatForM (Stream.fromList [1,2,3]) $ \x -> do      liftIO $ putStrLn (show x)      pure $ Stream.concatForM (Stream.fromList [4,5,6]) $ \y -> do        when (x == 1) $ liftIO $ putStrLn (show y)        pure $ Stream.fromPure (x, y):}145623[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]
valueconcatIterate
  1. :: Monad m
  2. => a -> Maybe (Stream m a)
  3. -> Stream m a
  4. -> Stream m a
#

Traverse the stream in depth first style (DFS). Map each element in the input stream to a stream and flatten, recursively map the resulting elements as well to a stream and flatten until no more streams are generated.

Example, list a directory tree using DFS:

Example3 expressions
f = either (Just . Dir.readEitherPaths id) (const Nothing)input = Stream.fromEffect (Left <$> Path.fromString ".")ls = Stream.concatIterate f input

This is equivalent to using concatIterateWith StreamK.append.

Pre-release

valueconcatIterateBfs
  1. :: Monad m
  2. => a -> Maybe (Stream m a)
  3. -> Stream m a
  4. -> Stream m a
#

Deprecated. Please use bfsConcatIterate instead.

Similar to concatIterate except that it traverses the stream in breadth first style (BFS). First, all the elements in the input stream are emitted, and then their traversals are emitted.

Example, list a directory tree using BFS:

Example3 expressions
f = either (Just . Dir.readEitherPaths id) (const Nothing)input = Stream.fromEffect (Left <$> Path.fromString ".")ls = Stream.bfsConcatIterate f input

Pre-release

valueconcatIterateDfs
  1. :: Monad m
  2. => a -> Maybe (Stream m a)
  3. -> Stream m a
  4. -> Stream m a
#

Deprecated. Please use concatIterate instead.

Traverse the stream in depth first style (DFS). Map each element in the input stream to a stream and flatten, recursively map the resulting elements as well to a stream and flatten until no more streams are generated.

Example, list a directory tree using DFS:

Example3 expressions
f = either (Just . Dir.readEitherPaths id) (const Nothing)input = Stream.fromEffect (Left <$> Path.fromString ".")ls = Stream.concatIterate f input

This is equivalent to using concatIterateWith StreamK.append.

Pre-release

valueconcatIterateScan
  1. :: Monad m
  2. => b -> a -> m b
  3. -> b -> m (Maybe (b, Stream m a))
  4. -> b
  5. -> Stream m a
#

Generate a stream from an initial state, scan and concat the stream, generate a stream again from the final state of the previous scan and repeat the process.

valueconcatMap :: Monad m => (a -> Stream m b) -> Stream m a -> Stream m b
#

Map a stream producing function on each element of the stream and then flatten the results into a single stream.

Example3 expressions
concatMap f = Stream.concat . fmap fconcatMap f = Stream.concatMapM (return . f)concatMap f = Stream.unfoldEach (Unfold.lmap f Unfold.fromStream)

See argument flipped version concatFor for more detailed documentation.

NOTE: We recommend using unfoldEach or unfoldCross instead of concatMap especially in performance critical code. unfoldEach is much faster than concatMap and matches its expressive power in terms of generating dependent inner streams, there is one important distinction though: the nesting structure when using unfoldEach is fixed statically in the code. In contrast, concatMap allows dynamic and arbitrary nesting through monadic composition. This means that deeply nested or programmatically determined levels of nesting are easier to express and compose with concatMap, though often at the cost of performance and fusion.

valueconcatMapM :: Monad m => (a -> m (Stream m b)) -> Stream m a -> Stream m b
#

Map a stream producing monadic function on each element of the stream and then flatten the results into a single stream. Since the stream generation function is monadic, unlike concatMap, it can produce an effect at the beginning of each iteration of the inner loop.

See unfoldEach for a faster alternative.

valuecross :: Monad m => Stream m a -> Stream m b -> Stream m (a, b)
#

Given a Stream m a and Stream m b generate a stream with all possible combinations of the tuple (a, b).

Definition:

Example1 expression
cross = Stream.crossWith (,)

The second stream is evaluated multiple times. If that is not desired it can be cached in an Array and then generated from the array before calling this function. Caching may also improve performance if the stream is expensive to evaluate.

Time: O(m x n)

Pre-release

valuecrossApply :: Functor f => Stream f (a -> b) -> Stream f a -> Stream f b
#

Apply a stream of functions to a stream of values and flatten the results.

Note that the second stream is evaluated multiple times.

Example1 expression
crossApply = Stream.crossWith id
valuecrossWith
  1. :: Monad m
  2. => a -> b -> c
  3. -> Stream m a
  4. -> Stream m b
  5. -> Stream m c
#

Definition:

Example1 expression
crossWith f m1 m2 = fmap f m1 `Stream.crossApply` m2

Note that the second stream is evaluated multiple times.

Also see "Streamly.Data.Unfold.crossWith" for fast fusible static cross product option.

valuedrain :: Monad m => Stream m a -> m ()
#

Definitions:

Example2 expressions
drain = Stream.fold Fold.draindrain = Stream.foldrM (\_ xs -> xs) (return ())

Run a stream, discarding the results.

valuefold :: Monad m => Fold m a b -> Stream m a -> m b
#

Fold a stream using the supplied left Fold and reducing the resulting expression strictly at each step. The behavior is similar to foldl'. A Fold can terminate early without consuming the full stream. See the documentation of individual Folds for termination behavior.

Definitions:

Example2 expressions
fold f = fmap fst . Stream.foldBreak ffold f = Stream.parse (Parser.fromFold f)

Example:

Example1 expression
Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)5050
valuefoldAddLazy :: Monad m => Fold m a b -> Stream m a -> Fold m a b
#

Append a stream to a fold lazily to build an accumulator incrementally.

Example, to continue folding a list of streams on the same sum fold:

Example3 expressions
streams = [Stream.fromList [1..5], Stream.fromList [6..10]]f = Prelude.foldl Stream.foldAddLazy Fold.sum streamsStream.fold f Stream.nil55
valuefoldBreak :: Monad m => Fold m a b -> Stream m a -> m (b, Stream m a)
#

Like fold but also returns the remaining stream. The resulting stream would be Stream.nil if the stream finished before the fold.

valuefoldEither
  1. :: Monad m
  2. => Fold m a b
  3. -> Stream m a
  4. -> m (Either (Fold m a b) (b, Stream m a))
#

Fold resulting in either breaking the stream or continuation of the fold. Instead of supplying the input stream in one go we can run the fold multiple times, each time supplying the next segment of the input stream. If the fold has not yet finished it returns a fold that can be run again otherwise it returns the fold result and the residual stream.

Internal

valuefoldMany :: Monad m => Fold m a b -> Stream m a -> Stream m b
#

Apply a terminating Fold repeatedly on a stream and emit the results in the output stream. If the last fold is empty, it's result is not emitted. This means if the input stream is empty the result is also an empty stream. See foldManyPost for an alternate behavior which always results in a non-empty stream even if the input stream is empty.

Definition:

Example1 expression
foldMany f = Stream.parseMany (Parser.fromFold f)

Example, empty stream, omits the empty fold value:

Example3 expressions
f = Fold.take 2 Fold.toListfmany = Stream.fold Fold.toList . Stream.foldMany ffmany $ Stream.fromList [][]

Example, omits the last empty fold value:

Example1 expression
fmany $ Stream.fromList [1..4][[1,2],[3,4]]

Example, last fold non-empty:

Example1 expression
fmany $ Stream.fromList [1..5][[1,2],[3,4],[5]]

Note that using a closed fold e.g. Fold.take 0, would result in an infinite stream on a non-empty input stream.

valuefoldManyPost :: Monad m => Fold m a b -> Stream m a -> Stream m b
#

Like foldMany but evaluates the fold even if the fold did not receive any input, therefore, always results in a non-empty output even on an empty stream (default result of the fold).

Example, empty stream, compare with foldMany:

Example3 expressions
f = Fold.take 2 Fold.toListfmany = Stream.fold Fold.toList . Stream.foldManyPost ffmany $ Stream.fromList [][[]]

Example, last empty fold is included, compare with foldMany:

Example1 expression
fmany $ Stream.fromList [1..4][[1,2],[3,4],[]]

Example, last fold non-empty, same as foldMany:

Example1 expression
fmany $ Stream.fromList [1..5][[1,2],[3,4],[5]]

Pre-release

valuefoldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
#

Right fold, lazy for lazy monads and pure streams, and strict for strict monads.

Please avoid using this routine in strict monads like IO unless you need a strict right fold. This is provided only for use in lazy monads (e.g. Identity) or pure streams. Note that with this signature it is not possible to implement a lazy foldr when the monad m is strict. In that case it would be strict in its accumulator and therefore would necessarily consume all its input.

Example1 expression
foldr f z = Stream.foldrM (\a b -> f a <$> b) (return z)

Note: This is similar to Fold.foldr' (the right fold via left fold), but could be more efficient.

valuefoldrM :: Monad m => (a -> m b -> m b) -> m b -> Stream m a -> m b
#

Right associative/lazy pull fold. foldrM build final stream constructs an output structure using the step function build. build is invoked with the next input element and the remaining (lazy) tail of the output structure. It builds a lazy output expression using the two. When the "tail structure" in the output expression is evaluated it calls build again thus lazily consuming the input stream until either the output expression built by build is free of the "tail" or the input is exhausted in which case final is used as the terminating case for the output structure. For more details see the description in the previous section.

Example, determine if any element is odd in a stream:

Example3 expressions
s = Stream.fromList (2:4:5:undefined)step x xs = if odd x then return True else xsStream.foldrM step (return False) sTrue
Example2 expressions
import Control.Monad (join)foldrM f z = join . Stream.foldr f z
valuefromEffect :: Applicative m => m a -> Stream m a
#

Create a singleton stream from a monadic action.

Example2 expressions
fromEffect m = m `Stream.consM` Stream.nilfromEffect = Stream.sequence . Stream.fromPure
Example1 expression
Stream.fold Fold.drain $ Stream.fromEffect (putStrLn "hello")hello
valuefromPure :: Applicative m => a -> Stream m a
#

Create a singleton stream from a pure value.

Example3 expressions
fromPure a = a `Stream.cons` Stream.nilfromPure = purefromPure = Stream.fromEffect . pure
valuegroupsOf :: Monad m => Int -> Fold m a b -> Stream m a -> Stream m b
#

Group the input stream into groups of n elements each and then fold each group using the provided fold function.

Definition:

Example1 expression
groupsOf n f = Stream.foldMany (Fold.take n f)

Usage:

Example1 expression
Stream.toList $ Stream.groupsOf 2 Fold.toList (Stream.enumerateFromTo 1 10)[[1,2],[3,4],[5,6],[7,8],[9,10]]

This can be considered as an n-fold version of take where we apply take repeatedly on the leftover stream until the stream exhausts.

valueindexEndBy :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
#

Like splitEndBy but generates a stream of (index, len) tuples marking the places where the predicate matches in the stream.

Example1 expression
Stream.toList $ Stream.indexEndBy (== '/') $ Stream.fromList "/home/harendra"[(0,1),(1,5),(6,8)]

Pre-release

valueindexEndBy_ :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
#

Like splitEndBy_ but generates a stream of (index, len) tuples marking the places where the predicate matches in the stream.

Example1 expression
Stream.toList $ Stream.indexEndBy_ (== '/') $ Stream.fromList "/home/harendra"[(0,0),(1,4),(6,8)]

Pre-release

valueindexOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
#

Deprecated. Please use indexEndBy_ instead.

Like splitEndBy_ but generates a stream of (index, len) tuples marking the places where the predicate matches in the stream.

Example1 expression
Stream.toList $ Stream.indexEndBy_ (== '/') $ Stream.fromList "/home/harendra"[(0,0),(1,4),(6,8)]

Pre-release

valueloop :: Monad m => Stream m b -> Stream m a -> Stream m (a, b)
#

Loop the supplied stream (first argument) around each element of the input stream (second argument) generating tuples. This is an argument flipped version of cross.

valueloopBy :: Monad m => Unfold m x b -> x -> Stream m a -> Stream m (a, b)
#

Loop by unfold. Unfold a value into a stream and nest it with the input stream. This is much faster than loop due to stream fusion.

valuemapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
#
Example1 expression
mapM f = Stream.sequence . fmap f

Apply a monadic function to each element of the stream and replace it with the output of the resulting action.

Example2 expressions
s = Stream.fromList ["a", "b", "c"]Stream.fold Fold.drain $ Stream.mapM putStr sabc

This is functional equivalent of an imperative loop.

valuenilM :: Applicative m => m b -> Stream m a
#

A stream that terminates without producing any output, but produces a side effect.

Example2 expressions
nilM action = Stream.before action Stream.nilStream.fold Fold.toList (Stream.nilM (print "nil"))"nil"[]

Pre-release

valuereduceIterateBfs :: Monad m => (a -> a -> m a) -> Stream m a -> m (Maybe a)
#

Deprecated. Please use bfsReduceIterate instead.

Binary BFS style reduce, folds a level entirely using the supplied fold function, collecting the outputs as next level of the tree, then repeats the same process on the next level. The last elements of a previously folded level are folded first.

valuesplitAt :: String -> Int -> [a] -> ([a], [a])
#

Inlined definition. Without the inline "seriallyparsertake" benchmark degrades and parseMany does not fuse. Even using "inline" at the callsite does not help.

valuetoList :: Monad m => Stream m a -> m [a]
#

Definitions:

Example2 expressions
toList = Stream.foldr (:) []toList = Stream.fold Fold.toList

Convert a stream into a list in the underlying monad. The list can be consumed lazily in a lazy monad (e.g. Identity). In a strict monad (e.g. IO) the whole list is generated and buffered before it can be consumed.

Warning! working on large lists accumulated as buffers in memory could be very inefficient, consider using Streamly.Data.Array instead.

Note that this could a bit more efficient compared to Stream.fold Fold.toList, and it can fuse with pure list consumers.

valueuncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
#

Decompose a stream into its head and tail. If the stream is empty, returns Nothing. If the stream is non-empty, returns Just (a, ma), where a is the head of the stream and ma its tail.

Properties:

Example2 expressions
Nothing <- Stream.uncons Stream.nilJust ("a", t) <- Stream.uncons (Stream.cons "a" Stream.nil)

This can be used to consume the stream in an imperative manner one element at a time, as it just breaks down the stream into individual elements and we can loop over them as we deem fit. For example, this can be used to convert a streamly stream into other stream types.

All the folds in this module can be expressed in terms of uncons, however, this is generally less efficient than specific folds because it takes apart the stream one element at a time, therefore, does not take adavantage of stream fusion.

foldBreak is a more general way of consuming a stream piecemeal.

Example1 expression
:{uncons xs = do    r <- Stream.foldBreak Fold.one xs    return $ case r of        (Nothing, _) -> Nothing        (Just h, t) -> Just (h, t):}
valueunfold :: Applicative m => Unfold m a b -> a -> Stream m b
#

Convert an Unfold into a stream by supplying it an input seed.

Example2 expressions
s = Stream.unfold Unfold.replicateM (3, putStrLn "hello")Stream.fold Fold.drain shellohellohello
valueunfoldCross
  1. :: Monad m
  2. => Unfold m (a, b) c
  3. -> Stream m a
  4. -> Stream m b
  5. -> Stream m c
#

Generates a cross product of two streams and then unfolds each tuple.

A two level nested loop much faster than concatMap based nesting.

Example1 expression
:{outerLoop =  flip Stream.mapM (Stream.fromList [1,2,3]) $ \x -> do      liftIO $ putStrLn (show x)      return xinnerLoop =  flip Stream.mapM (Stream.fromList [4,5,6]) $ \y -> do      -- liftIO $ putStrLn (show y)      return yinnerUnfold =  flip Unfold.mapM Unfold.identity $ \(x,y) -> do     when (x == 1) $ liftIO $ putStrLn (show y)     pure $ (x, y):}
Example1 expression
Stream.toList $ Stream.unfoldCross innerUnfold outerLoop innerLoop145623[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]

Note: unfoldEach may generate faster code, so use that when possible. Also see "Streamly.Data.Unfold.cross" for fast fusible static cross product option.

valueunfoldEach :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

unfoldEach unfold stream uses unfold to map the input stream elements to streams and then flattens the generated streams into a single output stream.

Like concatMap but uses an Unfold for stream generation. Unlike concatMap this can fuse the Unfold code with the inner loop and therefore provide many times better performance.

Example1 expression
concatMap f = Stream.unfoldEach (Unfold.lmap f Unfold.fromStream)

Here is an example of a two level nested loop much faster than concatMap based nesting.

Example1 expression
:{outerLoop =  flip Stream.mapM (Stream.fromList [1,2,3]) $ \x -> do      liftIO $ putStrLn (show x)      return xinnerUnfold = Unfold.carry $ Unfold.lmap (const [4,5,6]) Unfold.fromListinnerLoop =     flip Unfold.mapM innerUnfold $ \(x, y) -> do         when (x == 1) $ liftIO $ putStrLn (show y)         pure $ (x, y):}
Example1 expression
Stream.toList $ Stream.unfoldEach innerLoop outerLoop145623[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]
valueunfoldIterate :: Monad m => Unfold m a a -> Stream m a -> Stream m a
#

Same as concatIterate but more efficient due to stream fusion.

Example, list a directory tree using DFS:

Example3 expressions
f = Unfold.either (Dir.eitherReaderPaths id) Unfold.nilinput = Stream.fromEffect (Left <$> Path.fromString ".")ls = Stream.unfoldIterate f input

Pre-release

valueunfoldIterateDfs :: Monad m => Unfold m a a -> Stream m a -> Stream m a
#

Deprecated. Please use unfoldIterate instead.

Same as concatIterate but more efficient due to stream fusion.

Example, list a directory tree using DFS:

Example3 expressions
f = Unfold.either (Dir.eitherReaderPaths id) Unfold.nilinput = Stream.fromEffect (Left <$> Path.fromString ".")ls = Stream.unfoldIterate f input

Pre-release

valueunfoldMany :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

Deprecated. Please use unfoldEach instead.

unfoldEach unfold stream uses unfold to map the input stream elements to streams and then flattens the generated streams into a single output stream.

Like concatMap but uses an Unfold for stream generation. Unlike concatMap this can fuse the Unfold code with the inner loop and therefore provide many times better performance.

Example1 expression
concatMap f = Stream.unfoldEach (Unfold.lmap f Unfold.fromStream)

Here is an example of a two level nested loop much faster than concatMap based nesting.

Example1 expression
:{outerLoop =  flip Stream.mapM (Stream.fromList [1,2,3]) $ \x -> do      liftIO $ putStrLn (show x)      return xinnerUnfold = Unfold.carry $ Unfold.lmap (const [4,5,6]) Unfold.fromListinnerLoop =     flip Unfold.mapM innerUnfold $ \(x, y) -> do         when (x == 1) $ liftIO $ putStrLn (show y)         pure $ (x, y):}
Example1 expression
Stream.toList $ Stream.unfoldEach innerLoop outerLoop145623[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]
valuezipWith
  1. :: Monad m
  2. => a -> b -> c
  3. -> Stream m a
  4. -> Stream m b
  5. -> Stream m c
#

WARNING! O(n^2) time complexity wrt number of streams. Suitable for statically fusing a small number of streams. Use the O(n) complexity StreamK.Streamly.Data.StreamK.zipWith otherwise.

Stream a is evaluated first, followed by stream b, the resulting elements a and b are then zipped using the supplied zip function and the result c is yielded to the consumer.

If stream a or stream b ends, the zipped stream ends. If stream b ends first, the element a from previous evaluation of stream a is discarded.

Example3 expressions
s1 = Stream.fromList [1,2,3]s2 = Stream.fromList [4,5,6]Stream.fold Fold.toList $ Stream.zipWith (+) s1 s2[5,7,9]
datadata Step s a
#

A stream is a succession of Steps. A Yield produces a single value and the next state of the stream. Stop indicates there are no more values in the stream.

Constructors

Instances1Functor
  • Functor (Step s)Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Step
newtypenewtype Nested (m :: Type -> Type) a
#

A newtype wrapper for the Stream type with a cross product style monad instance.

A Monad bind behaves like a for loop:

Example1 expression
:{Stream.fold Fold.toList $ Stream.unNested $ do    x <- Stream.Nested $ Stream.fromList [1,2]    -- Perform the following actions for each x in the stream    return x:}[1,2]

Nested monad binds behave like nested for loops:

Example1 expression
:{Stream.fold Fold.toList $ Stream.unNested $ do    x <- Stream.Nested $ Stream.fromList [1,2]    y <- Stream.Nested $ Stream.fromList [3,4]    -- Perform the following actions for each x, for each y    return (x, y):}[(1,3),(1,4),(2,3),(2,4)]

Constructors

Instances14MonadTrans, Monad, Functor, Applicative, Foldable, MonadIO, …
datadata Stream (m :: Type -> Type) a
#

A stream consists of a step function that generates the next step given a current state, and the current state.

Constructors

Instances9Functor, Foldable, IsList, Eq, Ord, Read, …
valueabsTimes :: MonadIO m => Stream m AbsTime
#

absTimes returns a stream of absolute timestamps using a clock of 10 ms granularity.

Example2 expressions
f = Fold.drainMapM printStream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.absTimesAbsTime (TimeSpec {sec = ..., nsec = ...})AbsTime (TimeSpec {sec = ..., nsec = ...})AbsTime (TimeSpec {sec = ..., nsec = ...})

Note: This API is not safe on 32-bit machines.

Pre-release

valueabsTimesWith :: MonadIO m => Double -> Stream m AbsTime
#

absTimesWith g returns a stream of absolute timestamps using a clock of granularity g specified in seconds. A low granularity clock is more expensive in terms of CPU usage. Any granularity lower than 1 ms is treated as 1 ms.

Example2 expressions
f = Fold.drainMapM printStream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.absTimesWith 0.01AbsTime (TimeSpec {sec = ..., nsec = ...})AbsTime (TimeSpec {sec = ..., nsec = ...})AbsTime (TimeSpec {sec = ..., nsec = ...})

Note: This API is not safe on 32-bit machines.

Pre-release

valuecons :: Applicative m => a -> Stream m a -> Stream m a
#

WARNING! O(n^2) time complexity wrt number of elements. Use the O(n) complexity StreamK.Streamly.Data.StreamK.cons unless you want to statically fuse just a few elements.

Fuse a pure value at the head of an existing stream::

Example2 expressions
s = 1 `Stream.cons` Stream.fromList [2,3]Stream.toList s[1,2,3]

Definition:

Example1 expression
cons x xs = return x `Stream.consM` xs
valuedurations :: Double -> t m RelTime64
#

durations g returns a stream of relative time values measuring the time elapsed since the immediate predecessor element of the stream was generated. The first element of the stream is always 0. durations uses a clock of granularity g specified in seconds. A low granularity clock is more expensive in terms of CPU usage. The minimum granularity is 1 millisecond. Durations lower than 1 ms will be 0.

Note: This API is not safe on 32-bit machines.

Unimplemented

valueenumerateFromFractional :: (Monad m, Fractional a) => a -> Stream m a
#

Numerically stable enumeration from a Fractional number in steps of size 1. enumerateFromFractional from generates a stream whose first element is from and the successive elements are in increments of 1. No overflow or underflow checks are performed.

This is the equivalent to enumFrom for Fractional types. For example:

Example1 expression
Stream.toList $ Stream.take 4 $ Stream.enumerateFromFractional 1.1[1.1,2.1,3.1,4.1]
valueenumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
#

Enumerate an Integral type. enumerateFromIntegral from generates a stream whose first element is from and the successive elements are in increments of 1. The stream is bounded by the size of the Integral type.

Example1 expression
Stream.toList $ Stream.take 4 $ Stream.enumerateFromIntegral (0 :: Int)[0,1,2,3]
valueenumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
#

enumerateFromStepIntegral from step generates an infinite stream whose first element is from and the successive elements are in increments of step.

CAUTION: This function is not safe for finite integral types. It does not check for overflow, underflow or bounds.

Example1 expression
Stream.toList $ Stream.take 4 $ Stream.enumerateFromStepIntegral 0 2[0,2,4,6]
Example1 expression
Stream.toList $ Stream.take 3 $ Stream.enumerateFromStepIntegral 0 (-2)[0,-2,-4]
valueenumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
#

For floating point numbers if the increment is less than the precision then it just gets lost. Therefore we cannot always increment it correctly by just repeated addition. 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15 9007199254740992 + 2 :: Double => 9.007199254740994e15

Instead we accumulate the increment counter and compute the increment every time before adding it to the starting number.

This works for Integrals as well as floating point numbers, but enumerateFromStepIntegral is faster for integrals.

valueenumerateFromThenFractional
  1. :: (Monad m, Fractional a)
  2. => a
  3. -> a
  4. -> Stream m a
#

Numerically stable enumeration from a Fractional number in steps. enumerateFromThenFractional from then generates a stream whose first element is from, the second element is then and the successive elements are in increments of then - from. No overflow or underflow checks are performed.

This is the equivalent of enumFromThen for Fractional types. For example:

Example1 expression
Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 2.1[1.1,2.1,3.1,4.1]
Example1 expression
Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 (-2.1)[1.1,-2.1,-5.300000000000001,-8.500000000000002]
valueenumerateFromThenIntegral
  1. :: (Monad m, Integral a, Bounded a)
  2. => a
  3. -> a
  4. -> Stream m a
#

Enumerate an Integral type in steps. enumerateFromThenIntegral from then generates a stream whose first element is from, the second element is then and the successive elements are in increments of then - from. The stream is bounded by the size of the Integral type.

Example1 expression
Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) 2[0,2,4,6]
Example1 expression
Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) (-2)[0,-2,-4,-6]
valueenumerateFromThenToFractional
  1. :: (Monad m, Fractional a, Ord a)
  2. => a
  3. -> a
  4. -> a
  5. -> Stream m a
#

Numerically stable enumeration from a Fractional number in steps up to a given limit. enumerateFromThenToFractional from then to generates a finite stream whose first element is from, the second element is then and the successive elements are in increments of then - from up to to.

This is the equivalent of enumFromThenTo for Fractional types. For example:

Example1 expression
Stream.toList $ Stream.enumerateFromThenToFractional 0.1 2 6[0.1,2.0,3.9,5.799999999999999]
Example1 expression
Stream.toList $ Stream.enumerateFromThenToFractional 0.1 (-2) (-6)[0.1,-2.0,-4.1000000000000005,-6.200000000000001]
valueenumerateFromThenToIntegral
  1. :: (Monad m, Integral a)
  2. => a
  3. -> a
  4. -> a
  5. -> Stream m a
#

Enumerate an Integral type in steps up to a given limit. enumerateFromThenToIntegral from then to generates a finite stream whose first element is from, the second element is then and the successive elements are in increments of then - from up to to.

Example1 expression
Stream.toList $ Stream.enumerateFromThenToIntegral 0 2 6[0,2,4,6]
Example1 expression
Stream.toList $ Stream.enumerateFromThenToIntegral 0 (-2) (-6)[0,-2,-4,-6]
valueenumerateFromToFractional
  1. :: (Monad m, Fractional a, Ord a)
  2. => a
  3. -> a
  4. -> Stream m a
#

Numerically stable enumeration from a Fractional number to a given limit. enumerateFromToFractional from to generates a finite stream whose first element is from and successive elements are in increments of 1 up to to.

This is the equivalent of enumFromTo for Fractional types. For example:

Example1 expression
Stream.toList $ Stream.enumerateFromToFractional 1.1 4[1.1,2.1,3.1,4.1]
Example1 expression
Stream.toList $ Stream.enumerateFromToFractional 1.1 4.6[1.1,2.1,3.1,4.1,5.1]

Notice that the last element is equal to the specified to value after rounding to the nearest integer.

valueenumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
#

Enumerate an Integral type up to a given limit. enumerateFromToIntegral from to generates a finite stream whose first element is from and successive elements are in increments of 1 up to to.

Example1 expression
Stream.toList $ Stream.enumerateFromToIntegral 0 4[0,1,2,3,4]
valuefromCString# :: Monad m => Addr# -> Stream m Word8
#

Read bytes from an immutable Addr# until a 0 byte is encountered, the 0 byte is not included in the stream.

Example2 expressions
:set -XMagicHashfromCString# addr = Stream.takeWhile (/= 0) $ Stream.fromPtr $ (Ptr addr :: Ptr Word8)

Unsafe: The caller is responsible for safe addressing.

Note that this is completely safe when reading from Haskell string literals because they are guaranteed to be NULL terminated:

Example1 expression
Stream.toList $ Stream.fromCString# "\1\2\3\0"#[1,2,3]
valuefromFoldable :: (Monad m, Foldable f) => f a -> Stream m a
#
Example1 expression
fromFoldable = Prelude.foldr Stream.cons Stream.nil

Construct a stream from a Foldable containing pure values:

/WARNING: O(n^2), suitable only for a small number of elements in the stream/

valuefromFoldableM :: (Monad m, Foldable f) => f (m a) -> Stream m a
#
Example1 expression
fromFoldableM = Prelude.foldr Stream.consM Stream.nil

Construct a stream from a Foldable containing pure values:

/WARNING: O(n^2), suitable only for a small number of elements in the stream/

valuefromPtrN :: (Monad m, Storable a) => Int -> Ptr a -> Stream m a
#

Take n Storable elements starting from an immutable Ptr onwards.

Example1 expression
fromPtrN n = Stream.take n . Stream.fromPtr

Unsafe: The caller is responsible for safe addressing.

Pre-release

valuefromW16CString# :: Monad m => Addr# -> Stream m Word16
#

Read Word16 from an immutable Addr# until a 0 Word16 is encountered, the 0 Word16 is not included in the stream.

Example2 expressions
:set -XMagicHashfromW16CString# addr = Stream.takeWhile (/= 0) $ Stream.fromPtr $ (Ptr addr :: Ptr Word16)

Unsafe: The caller is responsible for safe addressing.

valueiterate :: Monad m => (a -> a) -> a -> Stream m a
#

Generate an infinite stream with x as the first element and each successive element derived by applying the function f on the previous element.

Example1 expression
Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1[1,2,3,4,5]
valueiterateM :: Monad m => (a -> m a) -> m a -> Stream m 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.

Example1 expression
:{Stream.iterateM (\x -> print x >> return (x + 1)) (return 0)    & Stream.take 3    & Stream.toList:}01[0,1,2]
valuenil :: Applicative m => Stream m a
#

A stream that terminates without producing any output or side effect.

Example1 expression
Stream.toList Stream.nil[]
valuerelTimes :: MonadIO m => Stream m RelTime64
#

relTimes returns a stream of relative time values starting from 0, using a clock of granularity 10 ms.

Example2 expressions
f = Fold.drainMapM printStream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimesRelTime64 (NanoSecond64 ...)RelTime64 (NanoSecond64 ...)RelTime64 (NanoSecond64 ...)

Note: This API is not safe on 32-bit machines.

Pre-release

relTimesWith g returns a stream of relative time values starting from 0, using a clock of granularity g specified in seconds. A low granularity clock is more expensive in terms of CPU usage. Any granularity lower than 1 ms is treated as 1 ms.

Example2 expressions
f = Fold.drainMapM printStream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimesWith 0.01RelTime64 (NanoSecond64 ...)RelTime64 (NanoSecond64 ...)RelTime64 (NanoSecond64 ...)

Note: This API is not safe on 32-bit machines.

Pre-release

valuerepeat :: Monad m => a -> Stream m a
#

Generate an infinite stream by repeating a pure value.

Example2 expressions
repeat = Stream.iterate idrepeat x = Stream.repeatM (pure x)
valuerepeatM :: Monad m => m a -> Stream m a
#
Example2 expressions
repeatM act = Stream.iterateM (const act) actrepeatM = Stream.sequence . Stream.repeat

Generate a stream by repeatedly executing a monadic action forever.

Example1 expression
:{repeatAction =       Stream.repeatM (threadDelay 1000000 >> print 1)     & Stream.take 10     & Stream.fold Fold.drain:}
valuereplicate :: Monad m => Int -> a -> Stream m a
#
Example2 expressions
replicate n = Stream.take n . Stream.repeatreplicate n x = Stream.replicateM n (pure x)

Generate a stream of length n by repeating a value n times.

valuereplicateM :: Monad m => Int -> m a -> Stream m a
#
Example1 expression
replicateM n = Stream.sequence . Stream.replicate n

Generate a stream by performing a monadic action n times.

valuetimeout :: AbsTime -> t m ()
#

Generate a singleton event at or after the specified absolute time. Note that this is different from a threadDelay, a threadDelay starts from the time when the action is evaluated, whereas if we use AbsTime based timeout it will immediately expire if the action is evaluated too late.

Unimplemented

valuetimes :: MonadIO m => Stream m (AbsTime, RelTime64)
#

times returns a stream of time value tuples with clock of 10 ms granularity. The first component of the tuple is an absolute time reference (epoch) denoting the start of the stream and the second component is a time relative to the reference.

Example2 expressions
f = Fold.drainMapM (\x -> print x >> threadDelay 1000000)Stream.fold f $ Stream.take 3 $ Stream.times(AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))(AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))(AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))

Note: This API is not safe on 32-bit machines.

Pre-release

valuetimesWith :: MonadIO m => Double -> Stream m (AbsTime, RelTime64)
#

timesWith g returns a stream of time value tuples. The first component of the tuple is an absolute time reference (epoch) denoting the start of the stream and the second component is a time relative to the reference.

The argument g specifies the granularity of the relative time in seconds. A lower granularity clock gives higher precision but is more expensive in terms of CPU usage. Any granularity lower than 1 ms is treated as 1 ms.

Example3 expressions
import Control.Concurrent (threadDelay)f = Fold.drainMapM (\x -> print x >> threadDelay 1000000)Stream.fold f $ Stream.take 3 $ Stream.timesWith 0.01(AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))(AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))(AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))

Note: This API is not safe on 32-bit machines.

Pre-release

valueunfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
#

Build a stream by unfolding a pure step function step starting from a seed s. The step function returns the next element in the stream and the next seed value. When it is done it returns Nothing and the stream ends. For example,

Example1 expression
:{let f b =        if b > 2        then Nothing        else Just (b, b + 1)in Stream.toList $ Stream.unfoldr f 0:}[0,1,2]
valueunfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
#

Build a stream by unfolding a monadic step function starting from a seed. The step function returns the next element in the stream and the next seed value. When it is done it returns Nothing and the stream ends. For example,

Example1 expression
:{let f b =        if b > 2        then return Nothing        else return (Just (b, b + 1))in Stream.toList $ Stream.unfoldrM f 0:}[0,1,2]
classclass Enum a => Enumerable a where
#

Types that can be enumerated as a stream. The operations in this type class are equivalent to those in the Enum type class, except that these generate a stream instead of a list. Use the functions in Streamly.Internal.Data.Stream.Enumeration module to define new instances.

Methods

  • enumerateFrom :: Monad m => a -> Stream m a

    enumerateFrom from generates a stream starting with the element from, enumerating up to maxBound when the type is Bounded or generating an infinite stream when the type is not Bounded.

    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)[0,1,2,3]

    For Fractional types, enumeration is numerically stable. However, no overflow or underflow checks are performed.

    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1[1.1,2.1,3.1,4.1]
  • enumerateFromTo :: Monad m => a -> a -> Stream m a

    Generate a finite stream starting with the element from, enumerating the type up to the value to. If to is smaller than from then an empty stream is returned.

    Example1 expression
    Stream.toList $ Stream.enumerateFromTo 0 4[0,1,2,3,4]

    For Fractional types, the last element is equal to the specified to value after rounding to the nearest integral value.

    Example1 expression
    Stream.toList $ Stream.enumerateFromTo 1.1 4[1.1,2.1,3.1,4.1]
    Example1 expression
    Stream.toList $ Stream.enumerateFromTo 1.1 4.6[1.1,2.1,3.1,4.1,5.1]
  • enumerateFromThen :: Monad m => a -> a -> Stream m a

    enumerateFromThen from then generates a stream whose first element is from, the second element is then and the successive elements are in increments of then - from. Enumeration can occur downwards or upwards depending on whether then comes before or after from. For Bounded types the stream ends when maxBound is reached, for unbounded types it keeps enumerating infinitely.

    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2[0,2,4,6]
    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)[0,-2,-4,-6]
  • enumerateFromThenTo :: Monad m => a -> a -> a -> Stream m a

    enumerateFromThenTo from then to generates a finite stream whose first element is from, the second element is then and the successive elements are in increments of then - from up to to. Enumeration can occur downwards or upwards depending on whether then comes before or after from.

    Example1 expression
    Stream.toList $ Stream.enumerateFromThenTo 0 2 6[0,2,4,6]
    Example1 expression
    Stream.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)[0,-2,-4,-6]
Instances21Enumerable, …
  • Enumerable IntegerDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable NaturalDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Int16Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Int32Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Int64Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Int8Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable BoolDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable CharDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable DoubleDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable FloatDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable IntDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable OrderingDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable WordDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Word16Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Word32Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Word64Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable Word8Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable ()Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Integral a => Enumerable (Ratio a)Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • Enumerable a => Enumerable (Identity a)Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
  • HasResolution a => Enumerable (Fixed a)Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Stream.Generate
valueisInfixOf
  1. :: (MonadIO m, Eq a, Enum a, Unbox a)
  2. => Stream m a
  3. -> Stream m a
  4. -> m Bool
#

Returns True if the first stream is an infix of the second. A stream is considered an infix of itself.

Example2 expressions
s = Stream.fromList "hello" :: Stream IO CharStream.isInfixOf s sTrue

Space: O(n) worst case where n is the length of the infix.

Pre-release

Requires Storable constraint

valueisPrefixOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
#

Returns True if the first stream is the same as or a prefix of the second. A stream is a prefix of itself.

Example1 expression
Stream.isPrefixOf (Stream.fromList "hello") (Stream.fromList "hello" :: Stream IO Char)True
valueisSubsequenceOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
#

Returns True if all the elements of the first stream occur, in order, in the second stream. The elements do not have to occur consecutively. A stream is a subsequence of itself.

Example1 expression
Stream.isSubsequenceOf (Stream.fromList "hlo") (Stream.fromList "hello" :: Stream IO Char)True
valueisSuffixOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
#

Returns True if the first stream is a suffix of the second. A stream is considered a suffix of itself.

Example1 expression
Stream.isSuffixOf (Stream.fromList "hello") (Stream.fromList "hello" :: Stream IO Char)True

Space: O(n), buffers entire input stream and the suffix.

Pre-release

Suboptimal - Help wanted.

valuemapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
#

Execute a monadic action for each element of the Stream

valueparse :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b)
#

Parse a stream using the supplied Parser.

Parsers (See Streamly.Internal.Data.Parser) are more powerful folds that add backtracking and error functionality to terminating folds. Unlike folds, parsers may not always result in a valid output, they may result in an error. For example:

Example1 expression
Stream.parse (Parser.takeEQ 1 Fold.drain) Stream.nilLeft (ParseError "takeEQ: Expecting exactly 1 elements, input terminated on 0")

Note: parse p is not the same as head . parseMany p on an empty stream.

valueparseD :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b)
#

Deprecated. Please use parse instead.

Parse a stream using the supplied Parser.

Parsers (See Streamly.Internal.Data.Parser) are more powerful folds that add backtracking and error functionality to terminating folds. Unlike folds, parsers may not always result in a valid output, they may result in an error. For example:

Example1 expression
Stream.parse (Parser.takeEQ 1 Fold.drain) Stream.nilLeft (ParseError "takeEQ: Expecting exactly 1 elements, input terminated on 0")

Note: parse p is not the same as head . parseMany p on an empty stream.

valueparsePos
  1. :: Monad m
  2. => Parser a m b
  3. -> Stream m a
  4. -> m (Either ParseErrorPos b)
#

Like parse but includes stream position information in the error messages.

Example1 expression
Stream.parsePos (Parser.takeEQ 2 Fold.drain) (Stream.fromList [1])Left (ParseErrorPos 1 "takeEQ: Expecting exactly 2 elements, input terminated on 1")
valuestripPrefix
  1. :: (Monad m, Eq a)
  2. => Stream m a
  3. -> Stream m a
  4. -> m (Maybe (Stream m a))
#

stripPrefix prefix input strips the prefix stream from the input stream if it is a prefix of input. Returns Nothing if the input does not start with the given prefix, stripped input otherwise. Returns Just nil when the prefix is the same as the input stream.

Space: O(1)

valuestripSuffix
  1. :: (Monad m, Eq a)
  2. => Stream m a
  3. -> Stream m a
  4. -> m (Maybe (Stream m a))
#

Drops the given suffix from a stream. Returns Nothing if the stream does not end with the given suffix. Returns Just nil when the suffix is the same as the stream.

It may be more efficient to convert the stream to an Array and use stripSuffix on that especially if the elements have a Storable or Prim instance.

Space: O(n), buffers the entire input stream as well as the suffix

Pre-release

valuetail :: Monad m => Stream m a -> m (Maybe (Stream m a))
#

Same as:

Example1 expression
tail = fmap (fmap snd) . Stream.uncons

Does not fuse, has the same performance as the StreamK version.

valueuncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
#

Decompose a stream into its head and tail. If the stream is empty, returns Nothing. If the stream is non-empty, returns Just (a, ma), where a is the head of the stream and ma its tail.

Properties:

Example2 expressions
Nothing <- Stream.uncons Stream.nilJust ("a", t) <- Stream.uncons (Stream.cons "a" Stream.nil)

This can be used to consume the stream in an imperative manner one element at a time, as it just breaks down the stream into individual elements and we can loop over them as we deem fit. For example, this can be used to convert a streamly stream into other stream types.

All the folds in this module can be expressed in terms of uncons, however, this is generally less efficient than specific folds because it takes apart the stream one element at a time, therefore, does not take adavantage of stream fusion.

foldBreak is a more general way of consuming a stream piecemeal.

Example1 expression
:{uncons xs = do    r <- Stream.foldBreak Fold.one xs    return $ case r of        (Nothing, _) -> Nothing        (Just h, t) -> Just (h, t):}
valueafterIO :: MonadIO m => IO b -> Stream m a -> Stream m a
#

Run the action IO b whenever the stream is evaluated to completion, or if it is garbage collected after a partial lazy evaluation.

The semantics of the action IO b are similar to the semantics of cleanup action in bracketIO.

See also afterUnsafe

valueafterUnsafe :: Monad m => m b -> Stream m a -> Stream m a
#

Like after, with following differences:

  • action m b won't run if the stream is garbage collected after partial evaluation.

  • Monad m does not require any other constraints.

  • has slightly better performance than after.

Same as the following, but with stream fusion:

Example1 expression
afterUnsafe action xs = xs <> Stream.nilM action

Pre-release

valuebefore :: Monad m => m b -> Stream m a -> Stream m a
#

Run the action m b before the stream yields its first element.

Same as the following but more efficient due to fusion:

Example1 expression
before action xs = Stream.concatMap (const xs) (Stream.fromEffect action)
valuebracketIO
  1. :: (MonadIO m, MonadCatch m)
  2. => IO b
  3. -> b -> IO c
  4. -> b -> Stream m a
  5. -> Stream m a
#

The alloc action IO b is executed with async exceptions disabled but keeping blocking operations interruptible (see mask). Uses the output b of the IO action as input to the function b -> Stream m a to generate an output stream.

b is usually a resource allocated under the IO monad, e.g. a file handle, that requires a cleanup after use. The cleanup is done using the b -> IO c action. bracketIO guarantees that the allocated resource is eventually (see details below) cleaned up even in the face of sync or async exceptions. If an exception occurs it is not caught, simply rethrown.

bracketIO only guarantees that the cleanup action runs, and it runs with async exceptions enabled. The action must ensure that it can successfully cleanup the resource in the face of sync or async exceptions.

Best case: Cleanup happens immediately in the following cases:

  • the stream is consumed completely

  • an exception occurs in the bracketed part of the pipeline

Worst case: In the following cases cleanup is deferred to GC.

  • the bracketed stream is partially consumed and abandoned

  • pipeline is aborted due to an exception outside the bracket

Use Streamly.Control.Exception.Streamly.Control.Exception.withAcquireIO for covering the entire pipeline with guaranteed cleanup at the end of bracket.

Observes exceptions only in the stream generation, and not in stream consumers.

See also: bracketUnsafe

Inhibits stream fusion

valuebracketIO'
  1. :: MonadIO m
  2. => AcquireIO
  3. -> IO b
  4. -> b -> IO c
  5. -> b -> Stream m a
  6. -> Stream m a
#

Like bracketIO but requires an Streamly.Control.Exception.AcquireIO reference in the underlying monad of the stream, and guarantees that all resources are freed before the scope of the monad level resource manager (Streamly.Control.Exception.Streamly.Control.Exception.withAcquireIO) ends. Where fusion matters, this combinator can be much faster than bracketIO as it allows stream fusion.

Best case: Cleanup happens immediately if the stream is consumed completely.

Worst case: In the following cases cleanup is guaranteed to occur at the end of the monad level bracket. However, if a GC occurs then cleanup will occur even earlier than that.

  • the bracketed stream is partially consumed and abandoned

  • pipeline is aborted due to an exception

This is the recommended default bracket operation.

Note: You can use Streamly.Control.Exception.acquire directly, instead of using this combinator, if you don’t need to release the resource when the stream ends. However, if you're using the stream inside another stream (like with concatMap), you usually do want to release it at the end of the stream.

Allows stream fusion

valuebracketIO''
  1. :: (MonadIO m, MonadCatch m)
  2. => AcquireIO
  3. -> IO b
  4. -> b -> IO c
  5. -> b -> Stream m a
  6. -> Stream m a
#

Like bracketIO, the only difference is that there is a guarantee that the resources will be freed at the end of the monad level bracket (Streamly.Control.Exception.AcquireIO).

Best case: Cleanup happens immediately in the following cases:

  • the stream is consumed completely

  • an exception occurs in the bracketed part of the pipeline

Worst case: In the following cases cleanup is guaranteed to occur at the end of the monad level bracket. However, if a GC occurs before that then cleanup will occur early.

  • the bracketed stream is partially consumed and abandoned

  • pipeline is aborted due to an exception outside the bracket

Note: Instead of using this combinator you can directly use Streamly.Control.Exception.acquire if you do not care about releasing the resource at the end of the stream and if you are not recovering from an exception using handle. You may want to care about releasing the resource at the end of a stream if you are using it in a nested manner (e.g. in concatMap).

Inhibits stream fusion

valuebracketIO3
  1. :: (MonadIO m, MonadCatch m)
  2. => IO b
  3. -> b -> IO c
  4. -> b -> IO d
  5. -> b -> IO e
  6. -> b -> Stream m a
  7. -> Stream m a
#

Like bracketIO but can use 3 separate cleanup actions depending on the mode of termination:

  1. When the stream stops normally

  2. When the stream is garbage collected

  3. When the stream encounters an exception

bracketIO3 before onStop onGC onException action runs action using the result of before. If the stream stops, onStop action is executed, if the stream is abandoned onGC is executed, if the stream encounters an exception onException is executed.

The exception is not caught, it is rethrown.

Inhibits stream fusion

Pre-release

valuebracketUnsafe
  1. :: MonadCatch m
  2. => m b
  3. -> b -> m c
  4. -> b -> Stream m a
  5. -> Stream m a
#

Like bracket but with following differences:

  • alloc action m b runs with async exceptions enabled

  • cleanup action b -> m c won't run if the stream is garbage collected after partial evaluation.

  • has slightly better performance than bracketIO.

Inhibits stream fusion

Pre-release

valuefinallyIO :: (MonadIO m, MonadCatch m) => IO b -> Stream m a -> Stream m a
#

Run the action IO b whenever the stream stream stops normally, aborts due to an exception or if it is garbage collected after a partial lazy evaluation.

The semantics of running the action IO b are similar to the cleanup action semantics described in bracketIO.

Example1 expression
finallyIO release stream = Stream.bracketIO (return ()) (const release) (const stream)

See also finallyIO' for stricter resource release guarantees.

See also finallyUnsafe

Inhibits stream fusion

valuefinallyUnsafe :: MonadCatch m => m b -> Stream m a -> Stream m a
#

Like finally with following differences:

  • action m b won't run if the stream is garbage collected after partial evaluation.

  • has slightly better performance than finallyIO.

Inhibits stream fusion

Pre-release

valuegbracket
  1. :: MonadIO m
  2. => IO c

    before

  3. -> (c -> IO d1)

    on normal stop

  4. -> (c -> e -> Stream m b -> IO (Stream m b))

    on exception

  5. -> (c -> IO d2)

    on GC without normal stop or exception

  6. -> (forall s. m s -> m (Either e s))

    try (exception handling)

  7. -> (c -> Stream m b)

    stream generator

  8. -> Stream m b
#

Run the alloc action m c with async exceptions disabled but keeping blocking operations interruptible (see mask). Use the output c as input to c -> Stream m b to generate an output stream. When generating the stream use the supplied try operation forall s. m s -> m (Either e s) to catch synchronous exceptions. If an exception occurs run the exception handler c -> e -> Stream m b -> m (Stream m b). Note that gbracket does not rethrow the exception, it has to be done by the exception handler if desired.

The cleanup action c -> m d, runs whenever the stream ends normally, due to a sync or async exception or if it gets garbage collected after a partial lazy evaluation. See bracket for the semantics of the cleanup action.

gbracket can express all other exception handling combinators.

Inhibits stream fusion

Pre-release

valuegbracket_
  1. :: Monad m
  2. => m c

    before

  3. -> (c -> m d)

    after, on normal stop

  4. -> (c -> e -> Stream m b -> m (Stream m b))

    on exception

  5. -> (forall s. m s -> m (Either e s))

    try (exception handling)

  6. -> (c -> Stream m b)

    stream generator

  7. -> Stream m b
#

Like gbracket but with following differences:

  • alloc action m c runs with async exceptions enabled

  • cleanup action c -> m d won't run if the stream is garbage collected after partial evaluation.

Inhibits stream fusion

Pre-release

valueghandle
  1. :: (MonadCatch m, Exception e)
  2. => e -> Stream m a -> m (Stream m a)
  3. -> Stream m a
  4. -> Stream m a
#

Like handle but the exception handler is also provided with the stream that generated the exception as input. The exception handler can thus re-evaluate the stream to retry the action that failed. The exception handler can again call ghandle on it to retry the action multiple times.

This is highly experimental. In a stream of actions we can map the stream with a retry combinator to retry each action on failure.

Inhibits stream fusion

Pre-release

valuehandle
  1. :: (MonadCatch m, Exception e)
  2. => e -> m (Stream m a)
  3. -> Stream m a
  4. -> Stream m a
#

When evaluating a stream if an exception occurs, stream evaluation aborts and the specified exception handler is run with the exception as argument. The exception is caught and handled unless the handler decides to rethrow it. Note that exception handling is not applied to the stream returned by the exception handler.

Observes exceptions only in the stream generation, and not in stream consumers.

Inhibits stream fusion

valueonException :: MonadCatch m => m b -> Stream m a -> Stream m a
#

Run the action m b if the stream evaluation is aborted due to an exception. The exception is not caught, simply rethrown.

Observes exceptions only in the stream generation, and not in stream consumers.

Inhibits stream fusion

valuewithAcquireIO
  1. :: (MonadIO m, MonadCatch m)
  2. => AcquireIO -> Stream m a
  3. -> Stream m a
#

Like bracketIO but with on-demand allocations and manual release facility.

Here is an example:

Example1 expression
:{close x h = do putStrLn $ "closing: " ++ x hClose h:}
Example1 expression
:{generate ref =     Stream.fromList ["file1", "file2"]   & Stream.mapM       (\x -> do           (h, release) <- Exception.acquire ref (openFile x ReadMode) (close x)           -- use h here           threadDelay 1000000           when (x == "file1") $ do               putStrLn $ "Manually releasing: " ++ x               release           return x       )   & Stream.trace print:}
Example1 expression
:{run =    Stream.withAcquireIO generate        & Stream.fold Fold.drain:}

In the above code, you should see the "closing:" message for both the files, and only once for each file. Make sure you create "file1" and "file2" before running it.

Here is an example for just registering hooks to be called eventually:

Example1 expression
:{generate ref =     Stream.fromList ["file1", "file2"]   & Stream.mapM       (\x -> do           Exception.register ref $ putStrLn $ "saw: " ++ x           threadDelay 1000000           return x       )   & Stream.trace print:}
Example1 expression
:{run =    Stream.withAcquireIO generate        & Stream.fold Fold.drain:}

In the above code, even if you interrupt the program with CTRL-C you should still see the "saw:" message for the elements seen before the interrupt.

See bracketIO documentation for the caveats related to partially consumed streams and async exceptions.

Use monad level bracket Streamly.Control.Exception.'Streamly..Control.Exception.withAcquireIO' for guaranteed cleanup in the entire pipeline, however, monad level bracket does not provide an automatic cleanup at the end of the stream; you can only release resources manually or via automatic cleanup at the end of the monad bracket. The end of stream cleanup is useful especially in nested streams where we want to cleanup at the end of every inner stream instead of waiting for the outer stream to end for cleaning up to happen.

valuewithAcquireIO' :: AcquireIO -> (AcquireIO -> Stream m a) -> Stream m a
#

We can also combine the stream local withAcquireIO with the global monad level bracket Streamly.Internal.Control.Exception.withAcquireIO. The release actions returned by the local allocator can be registered to be called by the monad level bracket. This way we can guarantee that in the worst case release actions happen at the end of bracket and do not depend on GC. This is the most powerful way of allocating resources on-demand with manual release inside a stream. If required a custom combinator can be written to register the local allocator's release in the global allocator automatically.

Unimplemented

valueliftInnerWith
  1. :: Monad (t m)
  2. => forall b. m b -> t m b
  3. -> Stream m a
  4. -> Stream (t m) a
#

Lift the inner monad m of a stream Stream m a to t m using the supplied lift function.

valuemorphInner :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
#

Transform the inner monad of a stream using a natural transformation.

Example, generalize the inner monad from Identity to any other:

Example1 expression
generalizeInner = Stream.morphInner (return . runIdentity)

Also known as hoist.

valuerunInnerWith
  1. :: Monad m
  2. => forall b. t m b -> m b
  3. -> Stream (t m) a
  4. -> Stream m a
#

Evaluate the inner monad of a stream using the supplied runner function.

valuerunInnerWithState
  1. :: Monad m
  2. => forall b. s -> t m b -> m (b, s)
  3. -> m s
  4. -> Stream (t m) a
  5. -> Stream m (s, a)
#

Evaluate the inner monad of a stream using the supplied stateful runner function and the initial state. The state returned by an invocation of the runner is supplied as input state to the next invocation.

valuefoldrT
  1. :: (Monad m, Monad (t m), MonadTrans t)
  2. => a -> t m b -> t m b
  3. -> t m b
  4. -> Stream m a
  5. -> t m b
#

Right fold to a transformer monad. This is the most general right fold function. foldrS is a special case of foldrT, however foldrS implementation can be more efficient:

Example1 expression
foldrS = Stream.foldrT
Example2 expressions
step f x xs = lift $ f x (runIdentityT xs)foldrM f z s = runIdentityT $ Stream.foldrT (step f) (lift z) s

foldrT can be used to translate streamly streams to other transformer monads e.g. to a different streaming type.

Pre-release

valueusingStateT
  1. :: Monad m
  2. => m s
  3. -> Stream (StateT s m) a -> Stream (StateT s m) b
  4. -> Stream m a
  5. -> Stream m b
#

Run a stateful (StateT) stream transformation using a given state.

Example1 expression
usingStateT s f = Stream.evalStateT s . f . Stream.liftInner

See also: scan

valuealtBfsUnfoldEach :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

Like bfsUnfoldEach but reverses the traversal direction after reaching the last stream and then after reaching the first stream, thus alternating the directions. This could be a little bit more efficient if the order of traversal is not important.

Example2 expressions
lists = Stream.fromList [[1,4,7],[2,5,8],[3,6,9]]Stream.toList $ Stream.altBfsUnfoldEach Unfold.fromList lists[1,2,3,6,5,4,7,8,9]

CAUTION! Do not use on infinite streams.

valuebfsUnfoldEach :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

Like unfoldEach but interleaves the resulting streams in a breadth first manner instead of appending them. Unfolds each element in the input stream to a stream and then interleave the resulting streams.

Example2 expressions
lists = Stream.fromList [[1,4,7],[2,5,8],[3,6,9]]Stream.toList $ Stream.bfsUnfoldEach Unfold.fromList lists[1,2,3,4,5,6,7,8,9]

CAUTION! Do not use on infinite streams.

valuedropInfix :: Stream m a -> Stream m a -> Stream m a
#

Drop all matching infix from the input stream if present. Infix stream may be consumed multiple times.

Space: O(n) where n is the length of the infix.

See also stripInfix.

Unimplemented

valuedropPrefix :: Stream m a -> Stream m a -> Stream m a
#

Drop prefix from the input stream if present.

Space: O(1)

See also stripPrefix.

Unimplemented

valuedropSuffix :: Stream m a -> Stream m a -> Stream m a
#

Drop suffix from the input stream if present. Suffix stream may be consumed multiple times.

Space: O(n) where n is the length of the suffix.

See also stripSuffix.

Unimplemented

valuefairConcatFor :: Monad m => Stream m a -> (a -> Stream m b) -> Stream m b
#

fairConcatFor is like concatFor but traverses the depth and breadth of nesting equally. Therefore, the outer and the inner loops in a nested loop get equal priority. It can be used to nest infinite streams without starving outer streams due to inner ones.

Given a stream of three streams:

1. [1,2,3]
2. [4,5,6]
3. [7,8,9]

Here, outer loop is the stream of streams and the inner loops are the individual streams. The traversal sweeps the diagonals in the above grid to give equal chance to outer and inner loops. The resulting stream is (1),(2,4),(3,5,7),(6,8),(9), diagonals are parenthesized for emphasis.

Looping

A single stream case is equivalent to concatFor:

Example1 expression
Stream.toList $ Stream.fairConcatFor (Stream.fromList [1,2]) $ \x -> Stream.fromPure x[1,2]

Fair Nested Looping

Multiple streams nest like for loops. The result is a cross product of the streams. However, the ordering of the results of the cross product is such that each stream gets consumed equally. In other words, inner iterations of a nested loop get the same priority as the outer iterations. Inner iterations do not finish completely before the outer iterations start.

Example1 expression
:{Stream.toList $ do    Stream.fairConcatFor (Stream.fromList [1,2,3]) $ \x ->     Stream.fairConcatFor (Stream.fromList [4,5,6]) $ \y ->      Stream.fromPure (x, y):}[(1,4),(1,5),(2,4),(1,6),(2,5),(3,4),(2,6),(3,5),(3,6)]

Nesting Infinite Streams

Example with infinite streams. Print all pairs in the cross product with sum less than a specified number.

Example1 expression
:{Stream.toList $ Stream.takeWhile (\(x,y) -> x + y < 6) $ Stream.fairConcatFor (Stream.fromList [1..]) $ \x ->    Stream.fairConcatFor (Stream.fromList [1..]) $ \y ->     Stream.fromPure (x, y):}[(1,1),(1,2),(2,1),(1,3),(2,2),(3,1),(1,4),(2,3),(3,2),(4,1)]

How the nesting works?

If we look at the cross product of [1,2,3], [4,5,6], the streams being combined using fairConcatFor are the following sequential loop iterations:

(1,4) (1,5) (1,6) -- first iteration of the outer loop
(2,4) (2,5) (2,6) -- second iteration of the outer loop
(3,4) (3,5) (3,6) -- third iteration of the outer loop

The result is a triangular or diagonal traversal of these iterations:

[(1,4),(1,5),(2,4),(1,6),(2,5),(3,4),(2,6),(3,5),(3,6)]

Non-Termination Cases

If one of the two interleaved streams does not produce an output at all and continues forever then the other stream will never get scheduled. This is because a stream is unscheduled only after it produces an output. This can lead to non-terminating programs, an example is provided below.

Example1 expression
:{oddsIf x = Stream.fromList (if x then [1,3..] else [2,4..])filterEven x = if even x then Stream.fromPure x else Stream.nil:}
Example1 expression
:{evens =    Stream.fairConcatFor (Stream.fromList [True,False]) $ \r ->     Stream.concatFor (oddsIf r) filterEven:}

The evens function does not terminate because, when r is True, the nested concatFor is a non-productive infinite loop, therefore, the outer loop never gets a chance to generate the False value.

But the following refactoring of the above code works as expected:

Example1 expression
:{mixed =     Stream.fairConcatFor (Stream.fromList [True,False]) $ \r ->         Stream.concatFor (oddsIf r) Stream.fromPure:}
Example2 expressions
evens = Stream.fairConcatFor mixed filterEvenStream.toList $ Stream.take 3 $ evens[2,4,6]

This works because in mixed both the streams being interleaved are productive.

Care should be taken how you write your program, keep in mind the scheduling implications. To avoid such scheduling problems in serial interleaving, you can use fairSchedFor or concurrent scheduling i.e. parFairConcatFor. Due to concurrent scheduling the other branch will make progress even if one is an infinite loop producing nothing.

Logic Programming

Streamly provides all operations for logic programming. It provides functionality equivalent to LogicT type from the logict package. The MonadLogic operations can be implemented using the available stream operations. For example, uncons is msplit, interleave corresponds to the interleave operation of MonadLogic, fairConcatFor is the fair bind (>>-) operation. fairSchedFor is an even better alternative for fair bind, it guarantees that non-productive infinite streams cannot block progress.

Related Operations

See also "Streamly.Internal.Data.StreamK.fairConcatFor".

valuefairSchedFor :: Monad m => Stream m a -> (a -> Stream m b) -> Stream m b
#

fairSchedFor is just like fairConcatFor, it traverses the depth and breadth of nesting equally. It maintains fairness among different levels of loop iterations. Therefore, the outer and the inner loops in a nested loop get equal priority. It can be used to nest infinite streams without starving outer streams due to inner ones.

There is one crucial difference, while fairConcatFor necessarily produces an output from one stream before it schedules the next, fairSchedFor schedules the next stream even if a stream did not produce an output. Thus it interleaves the CPU rather than the outputs of the streams. Thus even if an infinite stream does not produce an output it can not block all other streams.

Note that the order of emitting the output from different streams may not be predictable, it depends on the skip points inside the stream. Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

Non-Productive Streams

Unlike in fairConcatFor, if one of the two interleaved streams does not produce an output at all and continues forever then the other stream will still get scheduled. The following program will hang forever for fairConcatFor but will work fine with fairSchedFor.

Example1 expression
:{oddsIf x = Stream.fromList (if x then [1,3..] else [2,4..])filterEven x = if even x then Stream.fromPure x else Stream.nil:}
Example1 expression
:{evens =    Stream.fairSchedFor (Stream.fromList [True,False]) $ \r ->     Stream.fairSchedFor (oddsIf r) filterEven:}
Example1 expression
Stream.toList $ Stream.take 3 $ evens[2,4,6]

When r is True, the nested fairSchedFor is a non-productive infinite loop, but still the outer loop gets a chance to generate the False value, and the evens function can produce output. The same code won't terminate if we use fairConcatFor instead of fairSchedFor. Thus even without explicit concurrency we can schedule multiple streams on the same CPU.

Logic Programming

When exploring large streams in logic programming, fairSchedFor can be used as a safe alternative to fairConcatFor as it cannot block due to non-productive infinite streams.

valuefairSchedMap :: Monad m => (a -> Stream m b) -> Stream m a -> Stream m b
#

See fairSchedFor for documentation.

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

valuefairUnfoldEach :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

See fairConcatFor for more details. This is similar except that this uses unfolds, therefore, it is much faster due to fusion.

Example1 expression
:{outerLoop = Stream.fromList [1,2,3]innerLoop = Unfold.carry $ Unfold.lmap (const [4,5,6]) Unfold.fromList:}
Example1 expression
Stream.toList $ Stream.fairUnfoldEach innerLoop outerLoop[(1,4),(1,5),(2,4),(1,6),(2,5),(3,4),(2,6),(3,5),(3,6)]
valuefairUnfoldSched :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

Similar to fairUnfoldEach but scheduling is independent of the output.

Example1 expression
:{outerLoop = Stream.fromList [1,2,3]innerLoop = Unfold.carry $ Unfold.lmap (const [4,5,6]) Unfold.fromList:}
Example1 expression
Stream.toList $ Stream.fairUnfoldSched innerLoop outerLoop[(1,4),(1,5),(2,4),(1,6),(2,5),(3,4),(2,6),(3,5),(3,6)]

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

valuefoldIterateM
  1. :: Monad m
  2. => b -> m (Fold m a b)
  3. -> m b
  4. -> Stream m a
  5. -> Stream m b
#

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.

Usage:

Example4 expressions
import Data.Monoid (Sum(..))f x = return (Fold.take 2 (Fold.sconcat x))s = fmap Sum $ Stream.fromList [1..10]Stream.fold Fold.toList $ fmap 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

valuegintercalateSuffix
  1. :: Monad m
  2. => Unfold m a c
  3. -> Stream m a
  4. -> Unfold m b c
  5. -> Stream m b
  6. -> Stream m c
#

Deprecated. Please use intercalateEndBy instead. Note the change in argument order.

Example1 expression
gintercalateSuffix u1 s1 u2 s2 = Stream.intercalateEndBy u2 s2 u1 s1
valuegroupsBy
  1. :: Monad m
  2. => a -> a -> Bool
  3. -> Fold m a b
  4. -> Stream m a
  5. -> Stream m b
#

Deprecated. Please use groupsWhile instead. Please note the change in the argument order of the comparison function.

The argument order of the comparison function in groupsWhile is different than that of groupsBy.

In groupsBy the comparison function takes the next element as the first argument and the previous element as the second argument. In groupsWhile the first argument is the previous element and second argument is the next element.

valuegroupsWhile
  1. :: Monad m
  2. => a -> a -> Bool
  3. -> Fold m a b
  4. -> Stream m a
  5. -> Stream m b
#

Keep collecting items in a group as long as the comparison function returns true. The comparison function is cmp old new where old is the first item in the group and new is the incoming item being tested for membership of the group. The collected items are folded by the supplied fold.

Definition:

Example1 expression
groupsWhile cmp f = Stream.parseMany (Parser.groupBy cmp f)
valueintercalateEndBy
  1. :: Monad m
  2. => Unfold m a c
  3. -> Stream m a
  4. -> Unfold m b c
  5. -> Stream m b
  6. -> Stream m c
#

See intercalateSepBy for detailed documentation.

You can think of this as interleaveEndBy on the stream of streams followed by concat. Same as the following but more efficient:

Example1 expression
intercalateEndBy u1 s1 u2 s2 = Stream.concat $ Stream.interleaveEndBy (fmap (Stream.unfold u1) s1) (fmap (Stream.unfold u2) s2)

Pre-release

valueintercalateSepBy
  1. :: Monad m
  2. => Unfold m b c
  3. -> Stream m b
  4. -> Unfold m a c
  5. -> Stream m a
  6. -> Stream m c
#

The first stream Stream m b is turned into a stream of streams by unfolding each element using the first unfold, similarly Stream m a is also turned into a stream of streams. The second stream of streams is interspersed with the streams from the first stream in an infix manner and then the resulting stream is flattened.

You can think of this as interleaveSepBy on the stream of streams followed by concat. Same as the following but more efficient:

Example1 expression
intercalateSepBy u1 s1 u2 s2 = Stream.concat $ Stream.interleaveSepBy (fmap (Stream.unfold u1) s1) (fmap (Stream.unfold u2) s2)

If the separator stream consists of nil streams then it becomes equivalent to unfoldEach:

Example1 expression
unfoldEach = Stream.intercalateSepBy (Unfold.nilM (const (return ()))) (Stream.repeat ())

Pre-release

valueinterleave :: Monad m => Stream m a -> Stream m a -> Stream m a
#

WARNING! O(n^2) time complexity wrt number of streams. Suitable for statically fusing a small number of streams. Use the O(n) complexity StreamK.Streamly.Data.StreamK.interleave otherwise.

Interleaves two streams, yielding one element from each stream alternately, starting from the first stream. When one stream is exhausted, all the remaining elements of the other stream are emitted in the output stream.

Both the streams are completely exhausted.

(a b c) (. . .) => a . b . c .
(a b c) (. .  ) => a . b . c
(a b  ) (. . .) => a . b .  .

Examples:

Example4 expressions
f x y = Stream.toList $ Stream.interleave (Stream.fromList x) (Stream.fromList y)f "abc" "...""a.b.c."f "abc" "..""a.b.c"f "ab" "...""a.b.."
valueinterleaveBeginBy :: Stream m a -> Stream m a -> Stream m a
#

Interleave the two streams such that the elements of the second stream are prefixed by the elements of the first stream. Interleaving stops when and only when the second stream is exhausted. Shortfall of the prefix stream is ignored and excess is discarded.

(. . .) (a b c) => . a . b . c
(. . .) (a b  ) => . a . b      -- additional . is discarded
(. .  ) (a b c) => . a . b c    -- missing . is ignored

Unimplemented

valueinterleaveEndBy :: Monad m => Stream m a -> Stream m a -> Stream m a
#

Like interleaveEndBy' but interleaving stops when and only when the second stream is exhausted. Shortfall of the suffix stream is ignored and excess is discarded.

(. . .) (a b c) => a . b . c .
(. .  ) (a b c) => a . b . c    -- missing . is ignored
(. . .) (a b  ) => a . b .      -- additional . is discarded
Example4 expressions
f x y = Stream.toList $ Stream.interleaveEndBy (Stream.fromList x) (Stream.fromList y)f "..." "abc""a.b.c."f ".." "abc""a.b.c"f "..." "ab""a.b."
valueinterleaveEndBy' :: Monad m => Stream m a -> Stream m a -> Stream m a
#

Interleave the two streams such that the elements of the second stream are ended by the elements of the first stream. If one of the streams is exhausted then interleaving stops.

(. . .) (a b c) => a . b . c .
(. .  ) (a b c) => a . b .      -- c is discarded
(. . .) (a b  ) => a . b .      -- . is discarded

Examples:

Example4 expressions
f x y = Stream.toList $ Stream.interleaveEndBy' (Stream.fromList x) (Stream.fromList y)f "..." "abc""a.b.c."f ".." "abc""a.b."f "..." "ab""a.b."

Definition:

Example1 expression
interleaveEndBy' s1 s2 = Stream.unfoldEach Unfold.fromTuple $ Stream.zipWith (,) s2 s1

Similarly, we can defined interleaveBeginBy' as:

Example1 expression
interleaveBeginBy' = flip interleaveEndBy'
valueinterleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
#

Deprecated. Please use flip interleaveEndBy' instead.

Like interleave but stops interleaving as soon as any of the two streams stops. The suffix Min in the name determines the stop behavior.

This is the same as interleaveEndBy' but it might emit an additional element at the end.

valueinterleaveSepBy :: Monad m => Stream m a -> Stream m a -> Stream m a
#

Like interleaveSepBy' but interleaving stops when and only when the second stream is exhausted. Shortfall of the infix stream is ignored and excess is discarded.

(. . .) (a b c) => a . b . c    -- additional . is discarded
(. .  ) (a b c) => a . b . c
(.    ) (a b c) => a . b c      -- missing . is ignored

Examples:

Example4 expressions
f x y = Stream.toList $ Stream.interleaveSepBy (Stream.fromList x) (Stream.fromList y)f "..." "abc""a.b.c"f ".." "abc""a.b.c"f "." "abc""a.bc"
valueinterleaveSepBy' :: Monad m => Stream m a -> Stream m a -> Stream m a
#

Interleave the two streams such that the elements of the first stream are infixed between the elements of the second stream. If one of the streams is exhausted then interleaving stops.

(. . .) (a b c) => a . b . c    -- additional . is discarded
(. .  ) (a b c) => a . b . c
(.    ) (a b c) => a . b        -- c is discarded
Example4 expressions
f x y = Stream.toList $ Stream.interleaveSepBy' (Stream.fromList x) (Stream.fromList y)f "..." "abc""a.b.c"f ".." "abc""a.b.c"f "." "abc""a.b"
valueinterpose :: Monad m => c -> Unfold m b c -> Stream m b -> Stream m c
#

Deprecated. Please use unfoldEachSepBy instead.

Unfold the elements of a stream, intersperse the given element between the unfolded streams and then concat them into a single stream.

Definition:

Example2 expressions
unfoldEachSepBy x = Stream.unfoldEachSepByM (return x)unfoldEachSepBy x = Stream.intercalateSepBy Unfold.identity (Stream.repeat x)

Usage:

Example1 expression
unwords = Stream.unfoldEachSepBy ' '

Pre-release

valueinterposeM :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
#

Deprecated. Please use unfoldEachSepByM instead.

Monadic variant of unfoldEachSepBy.

Definition:

Example1 expression
unfoldEachSepByM x = Stream.intercalateSepBy Unfold.identity (Stream.repeatM x)
valueinterposeSuffix :: Monad m => c -> Unfold m b c -> Stream m b -> Stream m c
#

Deprecated. Please use unfoldEachEndBy instead.

Unfold the elements of a stream, append the given element after each unfolded stream and then concat them into a single stream.

Definition:

Example1 expression
unfoldEachEndBy x = Stream.intercalateEndBy Unfold.identity (Stream.repeat x)

Usage:

Example1 expression
unlines = Stream.unfoldEachEndBy '\n'

Pre-release

valueinterposeSuffixM
  1. :: Monad m
  2. => m c
  3. -> Unfold m b c
  4. -> Stream m b
  5. -> Stream m c
#

Deprecated. Please use unfoldEachEndByM instead.

Monadic variant of unfoldEachEndBy.

Definition:

Example1 expression
unfoldEachEndByM x = Stream.intercalateEndBy Unfold.identity (Stream.repeatM x)
valuemergeBy
  1. :: Monad m
  2. => a -> a -> Ordering
  3. -> Stream m a
  4. -> Stream m a
  5. -> Stream m a
#

WARNING! O(n^2) time complexity wrt number of streams. Suitable for statically fusing a small number of streams. Use the O(n) complexity StreamK.Streamly.Data.StreamK.mergeBy otherwise.

Merge two streams using a comparison function. The head elements of both the streams are compared and the smaller of the two elements is emitted, if both elements are equal then the element from the first stream is used first.

If the streams are sorted in ascending order, the resulting stream would also remain sorted in ascending order.

Example3 expressions
s1 = Stream.fromList [1,3,5]s2 = Stream.fromList [2,4,6,8]Stream.fold Fold.toList $ Stream.mergeBy compare s1 s2[1,2,3,4,5,6,8]
valuemergeByM
  1. :: Monad m
  2. => a -> a -> m Ordering
  3. -> Stream m a
  4. -> Stream m a
  5. -> Stream m a
#

Like mergeBy but with a monadic comparison function.

Example, to merge two streams randomly:

> randomly _ _ = randomIO >>= x -> return $ if x then LT else GT
> Stream.toList $ Stream.mergeByM randomly (Stream.fromList [1,1,1,1]) (Stream.fromList [2,2,2,2])
[2,1,2,2,2,1,1,1]

Example, merge two streams in a proportion of 2:1:

Example3 expressions
:set -fno-warn-unrecognised-warning-flags:set -fno-warn-x-partial:{do let s1 = Stream.fromList [1,1,1,1,1,1]     s2 = Stream.fromList [2,2,2] let proportionately m n = do      ref <- newIORef $ cycle $ Prelude.concat [Prelude.replicate m LT, Prelude.replicate n GT]      return $ \_ _ -> do         r <- readIORef ref         writeIORef ref $ Prelude.tail r         return $ Prelude.head r f <- proportionately 2 1 xs <- Stream.fold Fold.toList $ Stream.mergeByM f s1 s2 print xs:}[1,1,2,1,1,2,1,1,2]
valueparseIterate
  1. :: Monad m
  2. => b -> Parser a m b
  3. -> b
  4. -> Stream m a
  5. -> Stream m (Either ParseError b)
#

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.

Example:

Example3 expressions
import Data.Monoid (Sum(..))s = Stream.fromList [1..10]Stream.toList $ fmap getSum $ Stream.catRights $ Stream.parseIterate (\b -> Parser.takeBetween 0 2 (Fold.sconcat b)) (Sum 0) $ fmap Sum s[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

valueparseMany
  1. :: Monad m
  2. => Parser a m b
  3. -> Stream m a
  4. -> Stream m (Either ParseError b)
#

Apply a Parser repeatedly on a stream and emit the parsed values in the output stream.

Usage:

Example3 expressions
s = Stream.fromList [1..10]parser = Parser.takeBetween 0 2 Fold.sumStream.toList $ Stream.parseMany parser s[Right 3,Right 7,Right 11,Right 15,Right 19]

This is the streaming equivalent of the Streamly.Data.Parser.many parse combinator.

Known Issues: When the parser fails there is no way to get the remaining stream.

valueparseManyTill :: Parser a m b -> Parser a m x -> Stream m a -> Stream m b
#

parseManyTill collect test stream tries the parser test on the input, if test fails it backtracks and tries collect, after collect succeeds test is tried again and so on. The parser stops when test succeeds. The output of test is discarded and the output of collect is emitted in the output stream. The parser fails if collect fails.

Unimplemented

valueroundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
#

Schedule the execution of two streams in a fair round-robin manner, executing each stream once, alternately. Execution of a stream may not necessarily result in an output, a stream may choose to Skip producing an element until later giving the other stream a chance to run. Therefore, this combinator fairly interleaves the execution of two streams rather than fairly interleaving the output of the two streams. This can be useful in co-operative multitasking without using explicit threads. This can be used as an alternative to async.

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

Pre-release

valueschedFor :: Monad m => Stream m a -> (a -> Stream m b) -> Stream m b
#

Similar to bfsConcatFor but scheduling is independent of output.

Example2 expressions
lists = Stream.fromList [[1,4,7],[2,5,8],[3,6,9]]Stream.toList $ Stream.schedFor lists $ \xs -> Stream.fromList xs[1,2,3,4,5,6,7,8,9]

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

CAUTION! Do not use on infinite streams.

valueschedForM :: Monad m => Stream m a -> (a -> m (Stream m b)) -> Stream m b
#

See SchedFor for documentation.

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

CAUTION! Do not use on infinite streams.

valueschedMap :: Monad m => (a -> Stream m b) -> Stream m a -> Stream m b
#

See SchedFor for documentation.

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

CAUTION! Do not use on infinite streams.

valueschedMapM :: Monad m => (a -> m (Stream m b)) -> Stream m a -> Stream m b
#

Round robin co-operative scheduling of multiple streams.

Like concatMap but schedules the generated streams in a round robin fashion. Note that it does not strive to interleave the outputs of the streams, just gives the streams a chance to run whether it produces an output or not. Therefore, the outputs may not seem to be fairly interleaved if a stream decides to skip the output.

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

CAUTION! Do not use on infinite streams.

valuesplitBeginBy_ :: (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
#

Split on a prefixed separator element, dropping the separator. The supplied Fold is applied on the split segments.

> splitOnPrefix' p xs = Stream.toList $ Stream.splitOnPrefix p (Fold.toList) (Stream.fromList xs)
> splitOnPrefix' (== .) ".a.b"
["a","b"]

An empty stream results in an empty output stream: > splitOnPrefix' (== .) "" []

An empty segment consisting of only a prefix is folded to the default output of the fold:

> splitOnPrefix' (== .) "."
[""]

> splitOnPrefix' (== .) ".a.b."
["a","b",""]

> splitOnPrefix' (== .) ".a..b"
["a","","b"]

A prefix is optional at the beginning of the stream:

> splitOnPrefix' (== .) "a"
["a"]

> splitOnPrefix' (== .) "a.b"
["a","b"]

splitOnPrefix is an inverse of intercalatePrefix with a single element:

Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList . Stream.splitOnPrefix (== '.') Fold.toList === id

Assuming the input stream does not contain the separator:

Stream.splitOnPrefix (== '.') Fold.toList . Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList === id

Unimplemented

valuesplitEndBySeq
  1. :: (MonadIO m, Unbox a, Enum a, Eq a)
  2. => Array a
  3. -> Fold m a b
  4. -> Stream m a
  5. -> Stream m b
#

Parses a sequence of tokens suffixed by a separator e.g. a;b;c; is parsed as a;, b;, c;. If the pattern is empty the input stream is returned as it is.

Equivalent to the following:

Example1 expression
splitEndBySeq pat f = Stream.foldMany (Fold.takeEndBySeq pat f)

Usage:

Example2 expressions
f p = Stream.splitEndBySeq (Array.fromList p) Fold.toListsplitEndBy p xs = Stream.fold Fold.toList $ f p (Stream.fromList xs)
Example1 expression
splitEndBy "" ""[]
Example1 expression
splitEndBy "" "a...b"["a",".",".",".","b"]
Example1 expression
splitEndBy ".." ""[]
Example1 expression
splitEndBy ".." "a...b"["a..",".b"]
Example1 expression
splitEndBy ".." "abc"["abc"]
Example1 expression
splitEndBy ".." ".."[".."]
Example1 expression
splitEndBy "." ".a"[".","a"]
Example1 expression
splitEndBy "." "a."["a."]

Uses Rabin-Karp algorithm for substring search.

valuesplitEndBySeq_
  1. :: (MonadIO m, Unbox a, Enum a, Eq a)
  2. => Array a
  3. -> Fold m a b
  4. -> Stream m a
  5. -> Stream m b
#

Like splitEndBySeq but drops the separators and returns only the tokens.

Equivalent to the following:

Example1 expression
splitEndBySeq_ pat f = Stream.foldMany (Fold.takeEndBySeq_ pat f)

Usage:

Example2 expressions
f p = Stream.splitEndBySeq_ (Array.fromList p) Fold.toListsplitEndBy_ p xs = Stream.fold Fold.toList $ f p (Stream.fromList xs)
Example1 expression
splitEndBy_ "" ""[]
Example1 expression
splitEndBy_ "" "a...b"["a",".",".",".","b"]
Example1 expression
splitEndBy_ ".." ""[]
Example1 expression
splitEndBy_ ".." "a...b"["a",".b"]
Example1 expression
splitEndBy_ ".." "abc"["abc"]
Example1 expression
splitEndBy_ ".." ".."[""]
Example1 expression
splitEndBy_ "." ".a"["","a"]
Example1 expression
splitEndBy_ "." "a."["a"]

Uses Rabin-Karp algorithm for substring search.

valuesplitOnSeq
  1. :: (MonadIO m, Unbox a, Enum a, Eq a)
  2. => Array a
  3. -> Fold m a b
  4. -> Stream m a
  5. -> Stream m b
#

Deprecated. Please use splitSepBySeq_ instead.

Like splitSepBy_ but splits the stream on a sequence of elements rather than a single element. Parses a sequence of tokens separated by an infixed separator e.g. a;b;c is parsed as a, b, c. If the pattern is empty then each element is a match, thus the fold is finalized on each element.

Example1 expression
splitSepBy p xs = Stream.fold Fold.toList $ Stream.splitSepBySeq_ (Array.fromList p) Fold.toList (Stream.fromList xs)
Example1 expression
splitSepBy "" ""[]
Example1 expression
splitSepBy "" "a...b"["a",".",".",".","b"]
Example1 expression
splitSepBy ".." ""[]
Example1 expression
splitSepBy ".." "a...b"["a",".b"]
Example1 expression
splitSepBy ".." "abc"["abc"]
Example1 expression
splitSepBy ".." ".."["",""]
Example1 expression
splitSepBy "." ".a"["","a"]
Example1 expression
splitSepBy "." "a."["a",""]

Uses Rabin-Karp algorithm for substring search.

valuesplitOnSuffixSeq
  1. :: (MonadIO m, Unbox a, Enum a, Eq a)
  2. => Bool
  3. -> Array a
  4. -> Fold m a b
  5. -> Stream m a
  6. -> Stream m b
#

splitOnSuffixSeq withSep pat fld input splits the input using pat as a suffixed separator, the resulting split segments are fed to the fold fld. If withSep is True then the separator sequence is also suffixed with the split segments.

Internal

valuesplitSepBySeq_
  1. :: (MonadIO m, Unbox a, Enum a, Eq a)
  2. => Array a
  3. -> Fold m a b
  4. -> Stream m a
  5. -> Stream m b
#

Like splitSepBy_ but splits the stream on a sequence of elements rather than a single element. Parses a sequence of tokens separated by an infixed separator e.g. a;b;c is parsed as a, b, c. If the pattern is empty then each element is a match, thus the fold is finalized on each element.

Example1 expression
splitSepBy p xs = Stream.fold Fold.toList $ Stream.splitSepBySeq_ (Array.fromList p) Fold.toList (Stream.fromList xs)
Example1 expression
splitSepBy "" ""[]
Example1 expression
splitSepBy "" "a...b"["a",".",".",".","b"]
Example1 expression
splitSepBy ".." ""[]
Example1 expression
splitSepBy ".." "a...b"["a",".b"]
Example1 expression
splitSepBy ".." "abc"["abc"]
Example1 expression
splitSepBy ".." ".."["",""]
Example1 expression
splitSepBy "." ".a"["","a"]
Example1 expression
splitSepBy "." "a."["a",""]

Uses Rabin-Karp algorithm for substring search.

valuetakeEndBySeq
  1. :: (MonadIO m, Unbox a, Enum a, Eq a)
  2. => Array a
  3. -> Stream m a
  4. -> Stream m a
#

Take the stream until the supplied sequence is encountered. Take the sequence as well and stop.

Usage:

Example4 expressions
f pat xs = Stream.toList $ Stream.takeEndBySeq (Array.fromList pat) $ Stream.fromList xsf "fgh" "abcdefghijk""abcdefgh"f "lmn" "abcdefghijk""abcdefghijk"f "" "abcdefghijk"""
valuetakeEndBySeq_
  1. :: (MonadIO m, Unbox a, Enum a, Eq a)
  2. => Array a
  3. -> Stream m a
  4. -> Stream m a
#

Take the stream until the supplied sequence is encountered. Do not take the sequence.

Usage:

Example4 expressions
f pat xs = Stream.toList $ Stream.takeEndBySeq_ (Array.fromList pat) $ Stream.fromList xsf "fgh" "abcdefghijk""abcde"f "lmn" "abcdefghijk""abcdefghijk"f "" "abcdefghijk"""
valueunfoldEachEndBy :: Monad m => c -> Unfold m b c -> Stream m b -> Stream m c
#

Unfold the elements of a stream, append the given element after each unfolded stream and then concat them into a single stream.

Definition:

Example1 expression
unfoldEachEndBy x = Stream.intercalateEndBy Unfold.identity (Stream.repeat x)

Usage:

Example1 expression
unlines = Stream.unfoldEachEndBy '\n'

Pre-release

valueunfoldEachEndBySeq
  1. :: Monad m
  2. => b
  3. -> Unfold m b c
  4. -> Stream m b
  5. -> Stream m c
#

Unfold each element of the stream, end each unfold by a sequence generated by unfolding the supplied value.

Definition:

Example2 expressions
unfoldEachEndBySeq a u = Stream.unfoldEach u . Stream.intersperseEndByM aunfoldEachEndBySeq a u = Stream.intercalateEndBy u (Stream.repeat a) u

Idioms:

Example2 expressions
intersperseEndByM x = Stream.unfoldEachEndBySeq x Unfold.identityunlines = Stream.unfoldEachEndBySeq "\n" Unfold.fromList

Usage:

Example2 expressions
input = Stream.fromList ["abc", "def", "ghi"]Stream.toList $ Stream.unfoldEachEndBySeq "\n" Unfold.fromList input"abc\ndef\nghi\n"
valueunfoldEachFoldBy :: Fold m b c -> Unfold m a b -> Stream m a -> Stream m c
#

Stream must be finite. Unfolds each element of the input stream to generate streams. After generating one element from each stream fold those using the supplied fold and emit the result in the output stream. Continue doing this until the streams are exhausted.

Unimplemented

valueunfoldEachSepBy :: Monad m => c -> Unfold m b c -> Stream m b -> Stream m c
#

Unfold the elements of a stream, intersperse the given element between the unfolded streams and then concat them into a single stream.

Definition:

Example2 expressions
unfoldEachSepBy x = Stream.unfoldEachSepByM (return x)unfoldEachSepBy x = Stream.intercalateSepBy Unfold.identity (Stream.repeat x)

Usage:

Example1 expression
unwords = Stream.unfoldEachSepBy ' '

Pre-release

valueunfoldEachSepBySeq
  1. :: Monad m
  2. => b
  3. -> Unfold m b c
  4. -> Stream m b
  5. -> Stream m c
#

Unfold each element of the stream, separate the successive unfolds by a sequence generated by unfolding the supplied value.

Definition:

Example2 expressions
unfoldEachSepBySeq a u = Stream.unfoldEach u . Stream.intersperse aunfoldEachSepBySeq a u = Stream.intercalateSepBy u (Stream.repeat a) u

Idioms:

Example2 expressions
intersperse x = Stream.unfoldEachSepBySeq x Unfold.identityunwords = Stream.unfoldEachSepBySeq " " Unfold.fromList

Usage:

Example2 expressions
input = Stream.fromList ["abc", "def", "ghi"]Stream.toList $ Stream.unfoldEachSepBySeq " " Unfold.fromList input"abc def ghi"
valueunfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

Deprecated. Please use altBfsUnfoldEach instead.

Like bfsUnfoldEach but reverses the traversal direction after reaching the last stream and then after reaching the first stream, thus alternating the directions. This could be a little bit more efficient if the order of traversal is not important.

Example2 expressions
lists = Stream.fromList [[1,4,7],[2,5,8],[3,6,9]]Stream.toList $ Stream.altBfsUnfoldEach Unfold.fromList lists[1,2,3,6,5,4,7,8,9]

CAUTION! Do not use on infinite streams.

valueunfoldRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

Deprecated. Please use unfoldSched instead.

Similar to bfsUnfoldEach but scheduling is independent of output.

This is an N-ary version of roundRobin.

Example2 expressions
lists = Stream.fromList [[1,4,7],[2,5,8],[3,6,9]]Stream.toList $ Stream.unfoldSched Unfold.fromList lists[1,2,3,4,5,6,7,8,9]

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

CAUTION! Do not use on infinite streams.

valueunfoldSched :: Monad m => Unfold m a b -> Stream m a -> Stream m b
#

Similar to bfsUnfoldEach but scheduling is independent of output.

This is an N-ary version of roundRobin.

Example2 expressions
lists = Stream.fromList [[1,4,7],[2,5,8],[3,6,9]]Stream.toList $ Stream.unfoldSched Unfold.fromList lists[1,2,3,4,5,6,7,8,9]

Scheduling is affected by the Skip constructor; implementations with more skips receive proportionally less scheduling time.

CAUTION! Do not use on infinite streams.

valuewordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
#

Split the stream after stripping leading, trailing, and repeated separators determined by the predicate supplied. The tokens after splitting are collected by the supplied fold. In other words, the tokens are parsed in the same way as words are parsed from whitespace separated text.

Example4 expressions
f x = Stream.toList $ Stream.wordsBy (== '.') Fold.toList $ Stream.fromList xf "a.b"["a","b"]f "a..b"["a","b"]f ".a..b."["a","b"]
valuecatEithers :: Monad m => Stream m (Either a a) -> Stream m a
#

Remove the either wrapper and flatten both lefts and as well as rights in the output stream.

Example1 expression
catEithers = fmap (either id id)

Pre-release

valuecatMaybes :: Monad m => Stream m (Maybe a) -> Stream m a
#

In a stream of Maybes, discard Nothings and unwrap Justs.

Example2 expressions
catMaybes = Stream.mapMaybe idcatMaybes = fmap fromJust . Stream.filter isJust

Pre-release

valuedelay :: MonadIO m => Double -> Stream m a -> Stream m a
#

Introduce a delay of specified seconds between elements of the stream.

Definition:

Example2 expressions
sleep n = liftIO $ threadDelay $ round $ n * 1000000delay = Stream.intersperseM_ . sleep

Example:

Example2 expressions
input = Stream.enumerateFromTo 1 3Stream.fold (Fold.drainMapM print) $ Stream.delay 1 input123
valuedelayPost :: MonadIO m => Double -> Stream m a -> Stream m a
#

Introduce a delay of specified seconds after consuming an element of a stream.

Definition:

Example2 expressions
sleep n = liftIO $ threadDelay $ round $ n * 1000000delayPost = Stream.intersperseEndByM_ . sleep

Example:

Example2 expressions
input = Stream.enumerateFromTo 1 3Stream.fold (Fold.drainMapM print) $ Stream.delayPost 1 input123

Pre-release

valuedelayPre :: MonadIO m => Double -> Stream m a -> Stream m a
#

Introduce a delay of specified seconds before consuming an element of a stream.

Definition:

Example2 expressions
sleep n = liftIO $ threadDelay $ round $ n * 1000000delayPre = Stream.intersperseBeginByM_ . sleep

Example:

Example2 expressions
input = Stream.enumerateFromTo 1 3Stream.fold (Fold.drainMapM print) $ Stream.delayPre 1 input123

Pre-release

valuedeleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
#

Deletes the first occurrence of the element in the stream that satisfies the given equality predicate.

Example2 expressions
input = Stream.fromList [1,3,3,5]Stream.fold Fold.toList $ Stream.deleteBy (==) 3 input[1,3,5]
valuedropLast :: Int -> Stream m a -> Stream m a
#

Drop n elements at the end of the stream.

O(n) space, where n is the number elements dropped.

Unimplemented

valuedropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
#

Drop elements in the stream as long as the predicate succeeds and then take the rest of the stream.

valuedropWhileLast :: (a -> Bool) -> Stream m a -> Stream m a
#

Drop all consecutive elements at the end of the stream for which the predicate is true.

O(n) space, where n is the number elements dropped.

Unimplemented

valueelemIndices :: (Monad m, Eq a) => a -> Stream m a -> Stream m Int
#

Find all the indices where the value of the element in the stream is equal to the given value.

Example1 expression
elemIndices a = Stream.findIndices (== a)
valuefilter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
#

Include only those elements that pass a predicate.

Example3 expressions
filter p = Stream.filterM (return . p)filter p = Stream.mapMaybe (\x -> if p x then Just x else Nothing)filter p = Stream.postscanlMaybe (Scanl.filtering p)
valuefilterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
#

Same as filter but with a monadic predicate.

Example2 expressions
f p x = p x >>= \r -> return $ if r then Just x else NothingfilterM p = Stream.mapMaybeM (f p)
valuefindIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
#

Find all the indices where the element in the stream satisfies the given predicate.

Example1 expression
findIndices p = Stream.postscanlMaybe (Scanl.findIndices p)
valueindexed :: Monad m => Stream m a -> Stream m (Int, a)
#
Example4 expressions
f = Scanl.mkScanl (\(i, _) x -> (i + 1, x)) (-1,undefined)indexed = Stream.postscanl findexed = Stream.zipWith (,) (Stream.enumerateFrom 0)indexedR n = fmap (\(i, a) -> (n - i, a)) . indexed

Pair each element in a stream with its index, starting from index 0.

Example1 expression
Stream.fold Fold.toList $ Stream.indexed $ Stream.fromList "hello"[(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
valueindexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
#
Example2 expressions
f n = Scanl.mkScanl (\(i, _) x -> (i - 1, x)) (n + 1,undefined)indexedR n = Stream.postscanl (f n)
Example2 expressions
s n = Stream.enumerateFromThen n (n - 1)indexedR n = Stream.zipWith (,) (s n)

Pair each element in a stream with its index, starting from the given index n and counting down.

Example1 expression
Stream.fold Fold.toList $ Stream.indexedR 10 $ Stream.fromList "hello"[(10,'h'),(9,'e'),(8,'l'),(7,'l'),(6,'o')]
valueinsertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
#

insertBy cmp elem stream inserts elem before the first element in stream that is less than elem when compared using cmp.

Example1 expression
insertBy cmp x = Stream.mergeBy cmp (Stream.fromPure x)
Example2 expressions
input = Stream.fromList [1,3,5]Stream.fold Fold.toList $ Stream.insertBy compare 2 input[1,2,3,5]
valueintersperse :: Monad m => a -> Stream m a -> Stream m a
#

Insert a pure value between successive elements of a stream. It does nothing if stream has less than two elements.

Definition:

Example4 expressions
intersperse x = Stream.intersperseM (return x)intersperse x = Stream.unfoldEachSepBy x Unfold.identityintersperse x = Stream.unfoldEachSepBySeq x Unfold.identityintersperse x = Stream.interleaveSepBy (Stream.repeat x)

Example:

Example3 expressions
f x y = Stream.toList $ Stream.intersperse x $ Stream.fromList yf ',' "abc""a,b,c"f ',' "a""a"
valueintersperseBeginByM_ :: Monad m => m b -> Stream m a -> Stream m a
#

Insert a side effect before every element of a stream.

Definition:

Example2 expressions
intersperseBeginByM_ = Stream.trace_intersperseBeginByM_ m = Stream.mapM (\x -> void m >> return x)

Usage:

Example2 expressions
f x y = Stream.fold Fold.drain $ Stream.trace putChar $ Stream.intersperseBeginByM_ x $ Stream.fromList yf (putChar '.') "abc".a.b.c

Same as trace_.

Pre-release

valueintersperseEndByEveryM :: Monad m => Int -> m a -> Stream m a -> Stream m a
#

Like intersperseEndByM but intersperses an effectful action into the input stream after every n elements and also after the last element.

Example:

Example6 expressions
input = Stream.fromList "hello"Stream.toList $ Stream.intersperseEndByEveryM 2 (return ',') input"he,ll,o,"f n x y = Stream.toList $ Stream.intersperseEndByEveryM n (pure x) $ Stream.fromList yf 2 ',' "abcdef""ab,cd,ef,"f 2 ',' "abcdefg""ab,cd,ef,g,"f 2 ',' "a""a,"

Pre-release

valueintersperseEndByM :: Monad m => m a -> Stream m a -> Stream m a
#

Insert an effect and its output after every element of a stream.

Definition:

Example1 expression
intersperseEndByM x = Stream.interleaveEndBy (Stream.repeatM x)

Usage:

Example3 expressions
f x y = Stream.toList $ Stream.intersperseEndByM (pure x) $ Stream.fromList yf ',' "abc""a,b,c,"f ',' "a""a,"

Pre-release

valueintersperseEndByM_ :: Monad m => m b -> Stream m a -> Stream m a
#

Insert an effect after every element of a stream.

Example:

Example3 expressions
f x y = Stream.fold Fold.drain $ Stream.trace putChar $ Stream.intersperseEndByM_ x $ Stream.fromList yf (putChar '.') "abc"a.b.c.f (putChar '.') "a"a.

Pre-release

valueintersperseEveryM :: Int -> m a -> Stream m a -> Stream m a
#

Intersperse a monadic action into the input stream after every n elements.

Definition:

> intersperseEveryM n x = Stream.interleaveEverySepBy n (Stream.repeatM x)

Idioms:

Example2 expressions
intersperseM = Stream.intersperseEveryM 1intersperse x = Stream.intersperseEveryM 1 (return x)

Usage:

> input = Stream.fromList "hello"
> Stream.toList $ Stream.intersperseEveryM 2 (return ',') input

"he,ll,o"

Unimplemented

valueintersperseM :: Monad m => m a -> Stream m a -> Stream m a
#

Effectful variant of intersperse. Insert an effect and its output between successive elements of a stream. It does nothing if stream has less than two elements.

Definition:

Example1 expression
intersperseM x = Stream.interleaveSepBy (Stream.repeatM x)
valueintersperseMPrefix_ :: Monad m => m b -> Stream m a -> Stream m a
#

Deprecated. Please use intersperseBeginByM_ instead.

Insert a side effect before every element of a stream.

Definition:

Example2 expressions
intersperseBeginByM_ = Stream.trace_intersperseBeginByM_ m = Stream.mapM (\x -> void m >> return x)

Usage:

Example2 expressions
f x y = Stream.fold Fold.drain $ Stream.trace putChar $ Stream.intersperseBeginByM_ x $ Stream.fromList yf (putChar '.') "abc".a.b.c

Same as trace_.

Pre-release

valueintersperseMSuffix :: Monad m => m a -> Stream m a -> Stream m a
#

Deprecated. Please use intersperseEndByM instead.

Insert an effect and its output after every element of a stream.

Definition:

Example1 expression
intersperseEndByM x = Stream.interleaveEndBy (Stream.repeatM x)

Usage:

Example3 expressions
f x y = Stream.toList $ Stream.intersperseEndByM (pure x) $ Stream.fromList yf ',' "abc""a,b,c,"f ',' "a""a,"

Pre-release

valueintersperseMSuffixWith :: Monad m => Int -> m a -> Stream m a -> Stream m a
#

Deprecated. Please use intersperseEndByEveryM instead.

Like intersperseEndByM but intersperses an effectful action into the input stream after every n elements and also after the last element.

Example:

Example6 expressions
input = Stream.fromList "hello"Stream.toList $ Stream.intersperseEndByEveryM 2 (return ',') input"he,ll,o,"f n x y = Stream.toList $ Stream.intersperseEndByEveryM n (pure x) $ Stream.fromList yf 2 ',' "abcdef""ab,cd,ef,"f 2 ',' "abcdefg""ab,cd,ef,g,"f 2 ',' "a""a,"

Pre-release

valueintersperseMSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
#

Deprecated. Please use intersperseEndByM_ instead.

Insert an effect after every element of a stream.

Example:

Example3 expressions
f x y = Stream.fold Fold.drain $ Stream.trace putChar $ Stream.intersperseEndByM_ x $ Stream.fromList yf (putChar '.') "abc"a.b.c.f (putChar '.') "a"a.

Pre-release

valueintersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
#

Perform a side effect between two successive elements of a stream. It does nothing if the stream has less than two elements.

Example3 expressions
f x y = Stream.fold Fold.drain $ Stream.trace putChar $ Stream.intersperseM_ x $ Stream.fromList yf (putChar '.') "abc"a.b.cf (putChar '.') "a"a

Pre-release

valuemapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
#

Map a Maybe returning function to a stream, filter out the Nothing elements, and return a stream of values extracted from Just.

Equivalent to:

Example1 expression
mapMaybe f = Stream.catMaybes . fmap f
valuemapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
#

Like mapMaybe but maps a monadic function.

Equivalent to:

Example1 expression
mapMaybeM f = Stream.catMaybes . Stream.mapM f
Example1 expression
mapM f = Stream.mapMaybeM (\x -> Just <$> f x)
valuepostscanl :: Monad m => Scanl m a b -> Stream m a -> Stream m b
#

Postscan a stream using the given fold. A postscan omits the initial (default) value of the accumulator and includes the final value.

Example1 expression
Stream.toList $ Stream.postscanl Scanl.latest (Stream.fromList [])[]

Compare with scan which includes the initial value as well:

Example1 expression
Stream.toList $ Stream.scanl Scanl.latest (Stream.fromList [])[Nothing]

The following example extracts the input stream up to a point where the running average of elements is no more than 10:

Example4 expressions
import Data.Maybe (fromJust)let avg = Scanl.teeWith (/) Scanl.sum (fmap fromIntegral Scanl.length)s = Stream.enumerateFromTo 1.0 100.0:{ Stream.fold Fold.toList  $ fmap (fromJust . fst)  $ Stream.takeWhile (\(_,x) -> x <= 10)  $ Stream.postscanl (Scanl.tee Scanl.latest avg) s:}[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]
valueprune :: (a -> Bool) -> Stream m a -> Stream m a
#

Strip all leading and trailing occurrences of an element passing a predicate and make all other consecutive occurrences uniq.

> prune p = Stream.dropWhileAround p $ Stream.uniqBy (x y -> p x && p y)
> Stream.prune isSpace (Stream.fromList "  hello      world!   ")
"hello world!"

Space: O(1)

Unimplemented

valuereassembleBy :: Fold m a b -> (a -> a -> Int) -> Stream m a -> Stream m b
#

Buffer until the next element in sequence arrives. The function argument determines the difference in sequence numbers. This could be useful in implementing sequenced streams, for example, TCP reassembly.

Unimplemented

valuereverse :: Monad m => Stream m a -> Stream m a
#

Returns the elements of the stream in reverse order. The stream must be finite. Note that this necessarily buffers the entire stream in memory.

Definition:

Example1 expression
reverse m = Stream.concatEffect $ Stream.fold Fold.toListRev m >>= return . Stream.fromList
valuerollingMap :: Monad m => (Maybe a -> a -> b) -> Stream m a -> Stream m b
#

Apply a function on every two successive elements of a stream. The first argument of the map function is the previous element and the second argument is the current element. When the current element is the first element, the previous element is Nothing.

Pre-release

valuerollingMap2 :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
#

Like rollingMap but requires at least two elements in the stream, returns an empty stream otherwise.

This is the stream equivalent of the list idiom zipWith f xs (tail xs).

Pre-release

valuesampleFromThen :: Monad m => Int -> Int -> Stream m a -> Stream m a
#

sampleFromThen offset stride takes the element at offset index and then every element at strides of stride.

Example1 expression
Stream.fold Fold.toList $ Stream.sampleFromThen 2 3 $ Stream.enumerateFromTo 0 10[2,5,8]
valuescanl :: Monad m => Scanl m a b -> Stream m a -> Stream m b
#

Strict left scan. Scan a stream using the given fold. Scan includes the initial (default) value of the accumulator as well as the final value. Compare with postscan which omits the initial value.

Example2 expressions
s = Stream.fromList [1..10]Stream.fold Fold.toList $ Stream.takeWhile (< 10) $ Stream.scanl Scanl.sum s[0,1,3,6]

See also: usingStateT

valuescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
#

Strict left scan. Like map, scanl' too is a one to one transformation, however it adds an extra element.

Example1 expression
Stream.toList $ Stream.scanl' (+) 0 $ Stream.fromList [1,2,3,4][0,1,3,6,10]
Example1 expression
Stream.toList $ Stream.scanl' (flip (:)) [] $ Stream.fromList [1,2,3,4][[],[1],[2,1],[3,2,1],[4,3,2,1]]

The output of scanl' is the initial value of the accumulator followed by all the intermediate steps and the final result of foldl'.

By streaming the accumulated state after each fold step, we can share the state across multiple stages of stream composition. Each stage can modify or extend the state, do some processing with it and emit it for the next stage, thus modularizing the stream processing. This can be useful in stateful or event-driven programming.

Consider the following monolithic example, computing the sum and the product of the elements in a stream in one go using a foldl':

Example1 expression
Stream.fold (Fold.foldl' (\(s, p) x -> (s + x, p * x)) (0,1)) $ Stream.fromList [1,2,3,4](10,24)

Using scanl' we can make it modular by computing the sum in the first stage and passing it down to the next stage for computing the product:

Example1 expression
:{  Stream.fold (Fold.foldl' (\(_, p) (s, x) -> (s, p * x)) (0,1))  $ Stream.scanl' (\(s, _) x -> (s + x, x)) (0,1)  $ Stream.fromList [1,2,3,4]:}(10,24)

IMPORTANT: scanl' evaluates the accumulator to WHNF. To avoid building lazy expressions inside the accumulator, it is recommended that a strict data structure is used for accumulator.

Example2 expressions
scanl' step z = Stream.scanl (Scanl.mkScanl step z)scanl' f z xs = Stream.scanlM' (\a b -> return (f a b)) (return z) xs

See also: usingStateT

valuescanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
#

Like scanl' but for a non-empty stream. The first element of the stream is used as the initial value of the accumulator. Does nothing if the stream is empty.

Example1 expression
Stream.toList $ Stream.scanl1' (+) $ Stream.fromList [1,2,3,4][1,3,6,10]
valuescanlMAfter'
  1. :: Monad m
  2. => b -> a -> m b
  3. -> m b
  4. -> b -> m b
  5. -> Stream m a
  6. -> Stream m b
#

scanlMAfter' accumulate initial done stream is like scanlM' except that it provides an additional done function to be applied on the accumulator when the stream stops. The result of done is also emitted in the stream.

This function can be used to allocate a resource in the beginning of the scan and release it when the stream ends or to flush the internal state of the scan at the end.

Pre-release

valuescanr :: Monad m => Scanr m a b -> Stream m a -> Stream m b
#

Use a lazy right Scanr to transform a stream.

The following example extracts the input stream up to a point where the running average of elements is no more than 10:

Example4 expressions
import Data.Maybe (fromJust)let avg = Scanr.teeWith (/) Scanr.sum (fmap fromIntegral Scanr.length)s = Stream.enumerateFromTo 1.0 100.0:{ Stream.fold Fold.toList  $ fmap fst  $ Stream.takeWhile (\(_,x) -> x <= 10)  $ Stream.scanr (Scanr.tee Scanr.identity avg) s:}[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]
valuesequence :: Monad m => Stream m (m a) -> Stream m a
#
Example1 expression
sequence = Stream.mapM id

Replace the elements of a stream of monadic actions with the outputs of those actions.

Example2 expressions
s = Stream.fromList [putStr "a", putStr "b", putStrLn "c"]Stream.fold Fold.drain $ Stream.sequence sabc
valuesplitOn :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
#

Deprecated. Please use splitSepBy_ instead. Note the difference in behavior on splitting empty stream.

valuesplitSepBy_
  1. :: Monad m
  2. => a -> Bool
  3. -> Fold m a b
  4. -> Stream m a
  5. -> Stream m b
#

Split on an infixed separator element, dropping the separator. The supplied Fold is applied on the split segments. Splits the stream on separator elements determined by the supplied predicate, separator is considered as infixed between two segments:

Definition:

Usage:

Example2 expressions
splitOn p xs = Stream.fold Fold.toList $ Stream.splitSepBy_ p Fold.toList (Stream.fromList xs)splitOn (== '.') "a.b"["a","b"]

Splitting an empty stream results in an empty stream i.e. zero splits:

Example1 expression
splitOn (== '.') ""[]

If the stream does not contain the separator then it results in a single split:

Example1 expression
splitOn (== '.') "abc"["abc"]

If one or both sides of the separator are missing then the empty segment on that side is folded to the default output of the fold:

Example1 expression
splitOn (== '.') "."["",""]
Example1 expression
splitOn (== '.') ".a"["","a"]
Example1 expression
splitOn (== '.') "a."["a",""]
Example1 expression
splitOn (== '.') "a..b"["a","","b"]

splitSepBy_ is an inverse of unfoldEachSepBy:

Stream.unfoldEachSepBy '.' Unfold.fromList . Stream.splitSepBy_ (== '.') Fold.toList === id

Assuming the input stream does not contain the separator:

Stream.splitSepBy_ (== '.') Fold.toList . Stream.unfoldEachSepBy '.' Unfold.fromList === id
valuestrideFromThen :: Monad m => Int -> Int -> Stream m a -> Stream m a
#

Deprecated. Please use sampleFromThen instead.

sampleFromThen offset stride takes the element at offset index and then every element at strides of stride.

Example1 expression
Stream.fold Fold.toList $ Stream.sampleFromThen 2 3 $ Stream.enumerateFromTo 0 10[2,5,8]
valuetailNonEmpty :: Monad m => Stream m a -> Stream m a
#

tail for non-empty streams, fails for empty stream case.

See also tail for a non-partial version of this function..

valuetakeWhileLast :: (a -> Bool) -> Stream m a -> Stream m a
#

Take all consecutive elements at the end of the stream for which the predicate is true.

O(n) space, where n is the number elements taken.

Unimplemented

valuetap :: Monad m => Fold m a b -> Stream m a -> Stream m a
#

Tap the data flowing through a stream into a Fold. For example, you may add a tap to log the contents flowing through the stream. The fold is used only for effects, its result is discarded.

                  Fold m a b
                      |
-----stream m a ---------------stream m a-----

Example2 expressions
s = Stream.enumerateFromTo 1 2Stream.fold Fold.drain $ Stream.tap (Fold.drainMapM print) s12

Compare with trace.

valuetimeIndexWith
  1. :: MonadIO m
  2. => Double
  3. -> Stream m a
  4. -> Stream m (RelTime64, a)
#

Pair each element in a stream with relative times starting from 0, using a clock with the specified granularity. The time is measured just before the element is consumed.

Example1 expression
Stream.fold Fold.toList $ Stream.timeIndexWith 0.01 $ Stream.delay 1 $ Stream.enumerateFromTo 1 3[(RelTime64 (NanoSecond64 ...),1),(RelTime64 (NanoSecond64 ...),2),(RelTime64 (NanoSecond64 ...),3)]

Pre-release

valuetimeIndexed :: MonadIO m => Stream m a -> Stream m (RelTime64, a)
#

Pair each element in a stream with relative times starting from 0, using a 10 ms granularity clock. The time is measured just before the element is consumed.

Example1 expression
Stream.fold Fold.toList $ Stream.timeIndexed $ Stream.delay 1 $ Stream.enumerateFromTo 1 3[(RelTime64 (NanoSecond64 ...),1),(RelTime64 (NanoSecond64 ...),2),(RelTime64 (NanoSecond64 ...),3)]

Pre-release

valuetimestampWith :: MonadIO m => Double -> Stream m a -> Stream m (AbsTime, a)
#

Pair each element in a stream with an absolute timestamp, using a clock of specified granularity. The timestamp is generated just before the element is consumed.

Example1 expression
Stream.fold Fold.toList $ Stream.timestampWith 0.01 $ Stream.delay 1 $ Stream.enumerateFromTo 1 3[(AbsTime (TimeSpec {sec = ..., nsec = ...}),1),(AbsTime (TimeSpec {sec = ..., nsec = ...}),2),(AbsTime (TimeSpec {sec = ..., nsec = ...}),3)]

Pre-release

valuetrace :: Monad m => (a -> m b) -> Stream m a -> Stream m a
#

Apply a monadic function to each element flowing through the stream and discard the results.

Example2 expressions
s = Stream.enumerateFromTo 1 2Stream.fold Fold.drain $ Stream.trace print s12

Compare with tap.

valuetrace_ :: Monad m => m b -> Stream m a -> Stream m a
#

Perform a side effect before yielding each element of the stream and discard the results.

Example2 expressions
s = Stream.enumerateFromTo 1 2Stream.fold Fold.drain $ Stream.trace_ (print "got here") s"got here""got here"

Same as intersperseMPrefix_ but always serial.

See also: trace

Pre-release

valueuniq :: (Eq a, Monad m) => Stream m a -> Stream m a
#

Drop repeated elements that are adjacent to each other.

Example1 expression
uniq = Stream.uniqBy (==)
valueuniqBy :: Monad m => (a -> a -> Bool) -> Stream m a -> Stream m a
#

Drop repeated elements that are adjacent to each other using the supplied comparison function.

Example1 expression
uniq = Stream.uniqBy (==)

To strip duplicate path separators:

Example3 expressions
input = Stream.fromList "//a//b"f x y = x == '/' && y == '/'Stream.fold Fold.toList $ Stream.uniqBy f input"/a/b"

Space: O(1)

Pre-release

valuewith
  1. :: Monad m
  2. => Stream m a -> Stream m (s, a)
  3. -> ((s, a) -> b) -> Stream m (s, a) -> Stream m (s, a)
  4. -> (s, a) -> b
  5. -> Stream m a
  6. -> Stream m a
#

Modify a Stream m a -> Stream m a stream transformation that accepts a predicate (a -> b) to accept ((s, a) -> b) instead, provided a transformation Stream m a -> Stream m (s, a). Convenient to filter with index or time.

Example1 expression
filterWithIndex = Stream.with Stream.indexed Stream.filter

Pre-release

valuedeleteFirstsBy
  1. :: Monad m
  2. => a -> a -> Bool
  3. -> Stream m a
  4. -> Stream m a
  5. -> Stream m a
#

Returns a subsequence of the first stream, deleting first occurrences of those elements that are present in the second stream. Note that this is not a commutative operation. This is similar to the Data.List.deleteFirstsBy.

Example2 expressions
f xs ys = Stream.fold Fold.toList $ Stream.deleteFirstsBy (==) (Stream.fromList xs) (Stream.fromList ys)f [1,2,2,3,3,5] [1,2,2,3,4][3,5]

The following holds:

deleteFirstsBy (==) (Stream.ordNub s2 `append` s1) s2 === s1
deleteFirstsBy (==) (Stream.ordNub s2 `interleave` s1) s2 === s1

First stream can be infinite, second stream must be finite.

Space: O(m) where m is the number of elements in the first stream.

Time: O(m x n) where m is the number of elements in the first stream and n is the number of elements in the second stream.

Pre-release

valueinnerJoin
  1. :: Monad m
  2. => a -> b -> Bool
  3. -> Stream m a
  4. -> Stream m b
  5. -> Stream m (a, b)
#

Like cross but emits only those tuples where a == b using the supplied equality predicate. This is essentially a cross intersection of two streams.

Definition:

Example1 expression
innerJoin eq s1 s2 = Stream.filter (\(a, b) -> a `eq` b) $ Stream.cross s1 s2

The second (inner) stream must be finite. Moreover, it must be either pure or capable of multiple evaluations. If not then the caller should cache it in an Array, if the type does not have an Unbox instance then use the Generic Data.Array.Generic.Array. Convert the array to stream before calling this function. Caching may also improve performance if the stream is expensive to evaluate.

If you care about performance this function should be your last choice among all inner joins. innerJoin is a much faster fused alternative. innerSortedJoin is a faster alternative when streams are sorted. innerOrdJoin is an order of magnitude faster alternative when the type has an Ord instance.

Note: Conceptually, this is a commutative operation. Result includes all the elements from the left and the right stream. The order of streams can be changed without affecting results, except for the ordering within the tuple.

Time: O(m x n)

Pre-release

valueintersectBy
  1. :: Monad m
  2. => a -> a -> Bool
  3. -> Stream m a
  4. -> Stream m a
  5. -> Stream m a
#

intersectBy returns a subsequence of the first stream which intersects with the second stream. Note that this is not a commutative operation unlike a set intersection, because of duplicate elements in the stream the order of the streams matters. This is similar to intersectBy. Note that intersectBy is a special case of innerJoin.

Example2 expressions
f s1 s2 = Stream.fold Fold.toList $ Stream.intersectBy (==) (Stream.fromList s1) (Stream.fromList s2)f [1,3,4,4,5] [2,3,4,5,5][3,4,4,5]

First stream can be infinite, the second stream must be finite and must be capable of multiple evaluations.

Space: O(n) where n is the number of elements in the second stream.

Time: O(m x n) where m is the number of elements in the first stream and n is the number of elements in the second stream.

Pre-release

valuesortedIntersectBy
  1. :: Monad m
  2. => a -> a -> Ordering
  3. -> Stream m a
  4. -> Stream m a
  5. -> Stream m a
#

Like intersectBy but assumes that the input streams are sorted in ascending order. To use it on streams sorted in descending order pass an inverted comparison function returning GT for less than and LT for greater than.

Both streams can be infinite.

Space: O(1)

Time: O(m+n)

Pre-release

valuesortedUnionBy
  1. :: a -> a -> Ordering
  2. -> Stream m a
  3. -> Stream m a
  4. -> Stream m a
#

A more efficient unionBy for sorted streams.

Note that the behavior is different from unionBy. In unionBy we append the unique elements from second stream only after exhausting the first one whereas in sorted streams we can determine unique elements early even when we are going through the first stream. Thus the result is an interleaving of the two streams, merging those elements from the second stream that are not present in the first.

Space: O(1)

Both streams can be infinite.

Unimplemented

valueunionBy
  1. :: MonadIO m
  2. => a -> a -> Bool
  3. -> Stream m a
  4. -> Stream m a
  5. -> Stream m a
#

Returns the first stream appended with those unique elements from the second stream that are not already present in the first stream. Note that this is not a commutative operation unlike a set union, argument order matters. The behavior is similar to Data.List.unionBy.

Equivalent to the following except that s2 is evaluated only once:

Example1 expression
unionBy eq s1 s2 = s1 `Stream.append` Stream.deleteFirstsBy eq s1 (Stream.ordNub s2)

Example:

Example2 expressions
f s1 s2 = Stream.fold Fold.toList $ Stream.unionBy (==) (Stream.fromList s1) (Stream.fromList s2)f [1,2,2,4] [1,1,2,3,3][1,2,2,4,3]

First stream can be infinite, but second stream must be finite. Note that if the first stream is infinite the union means just the first stream. Thus union is useful only when both streams are finite. See sortedUnionBy where union can work on infinite streams if they are sorted.

Space: O(n)

Time: O(m x n)

Pre-release

valueinnerOrdJoin
  1. :: (Monad m, Ord k)
  2. => Stream m (k, a)
  3. -> Stream m (k, b)
  4. -> Stream m (k, a, b)
#

innerJoin specialized to Ord types for better performance.

If the input streams have duplicate keys, the behavior is undefined.

For space efficiency use the smaller stream as the second stream.

Space: O(n)

Time: O(m + n)

Pre-release

valueleftJoin
  1. :: Monad m
  2. => a -> b -> Bool
  3. -> Stream m a
  4. -> Stream m b
  5. -> Stream m (a, Maybe b)
#

Like innerJoin but emits (a, Just b) whenever a and b are equal, for those a's that are not equal to any b emits (a, Nothing).

This is a generalization of innerJoin to include all elements from the left stream and not just those which have an equal in the right stream. This is not a commutative operation, the order of the stream arguments matters.

All the caveats mentioned in innerJoin apply here as well. Right join is not provided because it is just a flipped left join:

Example1 expression
rightJoin eq = flip (Stream.leftJoin eq)

Space: O(n) assuming the second stream is cached in memory.

Time: O(m x n)

Unimplemented

valueordNub :: (Monad m, Ord a) => Stream m a -> Stream m a
#

nub specialized to Ord types for better performance. Returns a subsequence of the stream removing any duplicate elements.

The memory used is proportional to the number of unique elements in the stream. One way to limit the memory is to use take on the resulting stream to limit the unique elements in the stream.

valueouterJoin
  1. :: MonadIO m
  2. => a -> b -> Bool
  3. -> Stream m a
  4. -> Stream m b
  5. -> Stream m (Maybe a, Maybe b)
#

Like leftJoin but emits a (Just a, Just b). Like leftJoin, for those a's that are not equal to any b emit (Just a, Nothing), but additionally, for those b's that are not equal to any a emit (Nothing, Just b).

This is a generalization of left join to include all the elements from the right stream as well, in other words it is a combination of left and right joins. This is a commutative operation. The order of stream arguments can be changed without affecting results, except for the ordering of elements in the resulting tuple.

For space efficiency use the smaller stream as the second stream.

Space: O(n)

Time: O(m x n)

Pre-release