Streams represented as chains of functions calls using Continuation Passing
Style (CPS), suitable for dynamically composing potentially large number of
streams.
Unlike the statically fused operations in Streamly.Data.Stream, StreamK
operations are less efficient, involving a function call overhead for each
element, but they exhibit linear O(n) time complexity wrt to the number of
stream compositions. Therefore, they are suitable for dynamically composing
streams e.g. appending potentially infinite streams in recursive loops.
While fused streams can be used to efficiently process elements as small as
a single byte, CPS streams are typically used on bigger chunks of data to
avoid the larger overhead per element. For more details See the Stream vs
StreamK section in the Streamly.Data.Stream module.
In addition to the combinators in this module, you can use operations from
Streamly.Data.Stream for StreamK as well by converting StreamK to Stream
(toStream), and vice-versa (fromStream). Please refer to
Streamly.Internal.Data.StreamK for more functions that have not yet been
released.
For documentation see the corresponding combinators in
Streamly.Data.Stream. Documentation has been omitted in this module unless
there is a difference worth mentioning or if the combinator does not exist
in Streamly.Data.Stream.
>>> import Streamly.Data.StreamK (StreamK)>>> import qualified Streamly.Data.Fold as Fold>>> import qualified Streamly.Data.Parser as Parser>>> import qualified Streamly.Data.Stream as Stream>>> import qualified Streamly.Data.StreamK as StreamK>>> import qualified Streamly.FileSystem.Dir as Dir
For APIs that have not been released yet.
Example2 expressions
>>> import qualified Streamly.Internal.Data.StreamK as StreamK>>> import qualified Streamly.Internal.FileSystem.Dir as Dir
Overview
0 declarations
Continuation passing style (CPS) stream implementation. The K in StreamK
stands for Kontinuation.
StreamK can be constructed like lists, except that they use nil instead of
'[]' and cons instead of :.
Semigroup (StreamKma)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.StreamK.Type
Monoid (StreamKma)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.StreamK.Type
typeItem (StreamKIdentitya) = aDefined in streamly-core-0.2.2 · Streamly.Internal.Data.StreamK.Type
Construction
0 declarations
Primitives
Primitives to construct a stream from pure values or monadic actions.
All other stream construction and generation combinators described later
can be expressed in terms of these primitives. However, the special
versions provided in this module can be much more efficient in some
cases. Users can create custom combinators using these primitives.
Unlike the operations in Streamly.Data.Stream, these operations can
be used to dynamically compose large number of streams e.g. using the
concatMapWith and mergeMapWith operations. They have a linear O(n)
time complexity wrt to the number of streams being composed.
Note: When joining many streams in a left associative manner earlier
streams will get exponential priority than the ones joining later. Because
of exponentially high weighting of left streams it can be used with
concatMapWith even on a large number of streams.
Merging of n streams can be performed by combining the streams pair
wise using mergeMapWith to give O(n * log n) time complexity. If used
with concatMapWith it will have O(n^2) performance.
Zipping of n streams can be performed by combining the streams pair
wise using mergeMapWith with O(n * log n) time complexity. If used
with concatMapWith it will have O(n^2) performance.
>>> crossWith f m1 m2 = fmap f m1 `StreamK.crossApply` m2
Note that the second stream is evaluated multiple times.
Stream of streams
3 declarations
Some useful idioms:
Example3 expressions
>>> concatFoldableWith f = Prelude.foldr f StreamK.nil>>> concatMapFoldableWith f g = Prelude.foldr (f . g) StreamK.nil>>> concatForFoldableWith f xs g = Prelude.foldr (f . g) StreamK.nil xs
Perform a concatMap using a specified concat strategy. The first
argument specifies a merge or concat function that is used to merge the
streams generated by the map function.
Combine streams in pairs using a binary combinator, the resulting streams
are then combined again in pairs recursively until we get to a single
combined stream. The composition would thus form a binary tree.
For example, you can sort a stream using merge sort like this:
Note that if the stream length is not a power of 2, the binary tree composed
by mergeMapWith would not be balanced, which may or may not be important
depending on what you are trying to achieve.
However, this combinator uses a parser to first split the input stream into
down and up sorted segments and then merges them to optimize sorting when
pre-sorted sequences exist in the input stream.
O(n) space
Exceptions
1 declaration
Please note that Stream type does not observe any exceptions from
the consumer of the stream whereas StreamK does.
Like Streamly.Data.Stream.Streamly.Data.Stream.handle but with one
significant difference, this function observes exceptions from the consumer
of the stream as well.
You can also convert StreamK to Stream and use exception handling from
Stream module:
Example1 expression
>>> handle f s = StreamK.fromStream $ Stream.handle (\e -> StreamK.toStream (f e)) (StreamK.toStream s)
Resource Management
1 declaration
Please note that Stream type does not observe any exceptions from
the consumer of the stream whereas StreamK does.
Like Streamly.Data.Stream.Streamly.Data.Stream.bracketIO but with one
significant difference, this function observes exceptions from the consumer
of the stream as well. Therefore, it cleans up the resource promptly when
the consumer encounters an exception.
You can also convert StreamK to Stream and use resource handling from
Stream module: