Result of unconsAsync
.
Result of unconsAsync
. Conceptually similar to a Future
. Can be forced via pull
or stream
.
Trivial catenable sequence.
Trivial catenable sequence. Supports O(1) append, and (amortized)
O(1) uncons
, such that walking the sequence via N successive uncons
steps takes O(N). Like a difference list, conversion to a Seq[A]
takes linear time, regardless of how the sequence is built up.
Segment with a known size and that allows index-based random access of elements.
Segment with a known size and that allows index-based random access of elements.
Chunk
s can be created for a variety of collection types using methods on the Chunk
companion
(e.g., Chunk.vector
, Chunk.seq
, Chunk.array
). Additionally, the Chunk
companion
defines a subtype of Chunk
for each primitive type, using an unboxed primitive array.
To work with unboxed arrays, use methods like toBytes
to convert a Chunk[Byte]
to a Chunk.Bytes
and then access the array directly.
This type intentionally has a very limited API. Most operations are defined on Segment
in a lazy/fusable
fashion. In general, better performance comes from fusing as many operations as possible. As such, the
chunk API is minimal, to encourage use of the fusable operations.
Some operations have a lazy/fusable definition (on Segment
) and a strict definition
on Chunk
. To call such operations, use the .strict
method -- e.g., c.strict.splitAt(3)
.
A stream transformation represented as a function from stream to stream.
A stream transformation represented as a function from stream to stream.
Pipes are typically applied with the through
operation on Stream
.
A stream transformation that combines two streams in to a single stream, represented as a function from two streams to a single stream.
A stream transformation that combines two streams in to a single stream, represented as a function from two streams to a single stream.
Pipe2
s are typically applied with the through2
operation on Stream
.
A p: Pull[F,O,R]
reads values from one or more streams, returns a
result of type R
, and produces a Stream[F,O]
when calling p.stream
.
A p: Pull[F,O,R]
reads values from one or more streams, returns a
result of type R
, and produces a Stream[F,O]
when calling p.stream
.
Any resources acquired by p
are freed following the call to stream
.
Much of the API of Pull
is defined in Pull.InvariantOps.
Laws:
Pull
forms a monad in R
with pure
and flatMap
:
pure >=> f == f
f >=> pure == f
(f >=> g) >=> h == f >=> (g >=> h)
where f >=> g
is defined as a => a flatMap f flatMap g
fail
is caught by onError
:
onError(fail(e))(f) == f(e)
Indicates that a stream evaluates no effects.
Indicates that a stream evaluates no effects.
A Stream[Pure,O]
can be safely converted to a Stream[F,O]
for all F
.
Provides the ability to schedule evaluation of thunks in the future.
Potentially infinite, pure sequence of values of type O
and a result of type R
.
Potentially infinite, pure sequence of values of type O
and a result of type R
.
All methods which return a Segment
support fusion with other arbitrary methods that
return Segment
s. This is similar to the staging approach described in
Stream Fusion, to Completeness, but without
code generation in staging.
Stack safety is ensured by tracking a fusion depth. If the depth reaches the
limit, the computation is trampolined using cats.Eval
.
The Chunk type is a subtype of Segment that supports efficient index-based random access.
Implementation notes:
emits
). As such,
segments should update state before invoking callbacks so that remainders can be computed
accurately.
A pipe that converts a stream to a Stream[F,Unit]
.
A pipe that converts a stream to a Stream[F,Unit]
.
Sinks are typically applied with the to
operation on Stream
.
A stream producing output of type O
and which may evaluate F
effects.
A stream producing output of type O
and which may evaluate F
effects. If F
is Pure, the stream evaluates no effects.
Much of the API of Stream
is defined in Stream.InvariantOps.
Laws (using infix syntax):
append
forms a monoid in conjunction with empty
:
empty append s == s
and s append empty == s
.(s1 append s2) append s3 == s1 append (s2 append s3)
And cons
is consistent with using ++
to prepend a single segment:
s.cons(seg) == Stream.segment(seg) ++ s
Stream.fail
propagates until being caught by onError
:
Stream.fail(e) onError h == h(e)
Stream.fail(e) ++ s == Stream.fail(e)
Stream.fail(e) flatMap f == Stream.fail(e)
Stream
forms a monad with emit
and flatMap
:
Stream.emit >=> f == f
(left identity)f >=> Stream.emit === f
(right identity - note weaker equality notion here)(f >=> g) >=> h == f >=> (g >=> h)
(associativity)
where Stream.emit(a)
is defined as segment(Segment.singleton(a)) and
f >=> g is defined as
a => a flatMap f flatMap g
The monad is the list-style sequencing monad:
(a ++ b) flatMap f == (a flatMap f) ++ (b flatMap f)
Stream.empty flatMap f == Stream.empty
Technical notes
Note: since the segment structure of the stream is observable, and
s flatMap Stream.emit
produces a stream of singleton segments,
the right identity law uses a weaker notion of equality, ===
which
normalizes both sides with respect to segment structure:
(s1 === s2) = normalize(s1) == normalize(s2)
where ==
is full equality
(a == b
iff f(a)
is identical to f(b)
for all f
)
normalize(s)
can be defined as s.flatMap(Stream.emit)
, which just
produces a singly-chunked stream from any input stream s
.
Note: For efficiency Stream.map
function operates on an entire
segment at a time and preserves segment structure, which differs from
the map
derived from the monad (s map f == s flatMap (f andThen Stream.emit)
)
which would produce singleton segments. In particular, if f
throws errors, the
segmented version will fail on the first segment with an error, while
the unsegmented version will fail on the first element with an error.
Exceptions in pure code like this are strongly discouraged.
Companion for Sink.
Provides utilities for asynchronous computations.
Provides utilities for working with streams of text (e.g., encoding byte streams to strings).