A strict, in-memory sequence of A
values.
A strict, in-memory sequence of A
values.
Chunks can be constructed via various constructor methods on the Chunk
companion object.
Chunks are internally specialized for both single element chunks and unboxed arrays of primitives.
Supports unboxed operations for booleans, bytes, longs, and doubles, using a
Chunk
implementation that is backed by an array of primitives. When possible,
operations on Chunk
preserves unboxed-ness. To get access the underlying
unboxed arrays, use toBooleans
, toBytes
, toLongs
, and toDoubles
.
Note: the NonEmptyChunk type is a subtype of Chunk
which is limited to chunks with at least
one element.
A currently open Stream[F,A]
which allows chunks to be pulled or pushed.
A currently open Stream[F,A]
which allows chunks to be pulled or pushed.
To get a handle from a stream, use Stream.open.
A chunk which has at least one element.
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
.
Allows acquiring elements from a stream in a resource safe way,
emitting elements of type O
, working with a resource of type R
,
and evaluating effects of type F
.
Allows acquiring elements from a stream in a resource safe way,
emitting elements of type O
, working with a resource of type R
,
and evaluating effects of type F
.
Laws:
or
forms a monoid in conjunction with done
:
or(done, p) == p
and or(p, done) == p
.or(or(p1,p2), p3) == or(p1, or(p2,p3))
fail
is caught by onError
:
onError(fail(e))(f) == f(e)
Pull
forms a monad 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
Indicates that a stream evaluates no effects.
Indicates that a stream evaluates no effects.
A Stream[Pure,O]
can be safely cast to a Stream[Nothing,O]
,
but Stream[Pure,O]
has better type inference properties in some places.
See usage in Stream.pull
.
Provides the ability to schedule evaluation of thunks in the future.
Tracks resources acquired while running a stream.
Tracks resources acquired while running a stream.
Note: Scope
is not typically used directly by user code.
A future that evaluates to a value of type A
and a Scope[F,Unit]
.
A future that evaluates to a value of type A
and a Scope[F,Unit]
.
To use a ScopedFuture
, convert to a Pull
(via f.pull
) or a Stream
(via f.stream
).
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
.
Provides a function for evaluating thunks, possibly asynchronously.
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 Nothing
or fs2.Pure
, the stream is pure.
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 push
is consistent with using append
to prepend a single chunk:
push(c)(s) == chunk(c) append s
fail
propagates until being caught by onError
:
fail(e) onError h == h(e)
fail(e) append s == fail(e)
fail(e) flatMap f == fail(e)
Stream
forms a monad with emit
and flatMap
:
emit >=> f == f
(left identity)f >=> emit === f
(right identity - note weaker equality notion here)(f >=> g) >=> h == f >=> (g >=> h)
(associativity)
where emit(a)
is defined as chunk(Chunk.singleton(a)) and
f >=> g is defined as
a => a flatMap f flatMap g
The monad is the list-style sequencing monad:
(a append b) flatMap f == (a flatMap f) append (b flatMap f)
empty flatMap f == empty
Technical notes
Note: since the chunk structure of the stream is observable, and
s flatMap (emit)
produces a stream of singleton chunks,
the right identity law uses a weaker notion of equality, ===
which
normalizes both sides with respect to chunk 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.repeatPull(_.echo1)
, which just
produces a singly-chunked stream from any input stream s
.
Note: For efficiency Stream.map
function operates on an entire
chunk at a time and preserves chunk structure, which differs from
the map
derived from the monad (s map f == s flatMap (f andThen emit)
)
which would produce singleton chunks. In particular, if f
throws errors, the
chunked version will fail on the first chunk with an error, while
the unchunked version will fail on the first element with an error.
Exceptions in pure code like this are strongly discouraged.
Trampolined computation producing an A
that may
include asynchronous steps.
Trampolined computation producing an A
that may
include asynchronous steps. Arbitrary monadic expressions involving
map
and flatMap
are guaranteed to use constant stack space.
In addition, using Task.async
, one may construct a Task
from
callback-based APIs. This makes Task
useful as a concurrency primitive
and as a control structure for wrapping callback-based APIs with a more
straightforward, monadic API.
Task is also exception-safe. Any exceptions raised during processing may
be accessed via the attempt
method, which converts a Task[A]
to a
Task[Attempt[A]]
.
Unlike scala.concurrent.Future
, map
and flatMap
do NOT spawn new
tasks and do not require an implicit ExecutionContext
. Instead, map
and flatMap
merely add to the current (trampolined) continuation that
will be run by the 'current' thread, unless explicitly forked via Task.start
.
Task
also differs from scala.concurrent.Future
in that it
does not represent a _running_ computation. Instead, we
reintroduce concurrency _explicitly_ using the Task.start
function.
This simplifies our implementation and makes code easier to reason about,
since the order of effects and the points of allowed concurrency are made
fully explicit and do not depend on Scala's evaluation order.
Provides utilities for asynchronous computations.
Provides utilities for working with streams concurrently.
Generic implementations of common pipes.
Generic implementations of common 2-argument pipes.
Provides utilities for working with streams of text (e.g., encoding byte streams to strings).
Type classes and other utilities used by fs2.
Type classes and other utilities used by fs2.
This package includes a minimal set of common functional type classes -- e.g., Functor, Applicative, Monad, Traverse -- along with some extensions that are more specialized like Suspendable, Catchable, Effect, and Async.
Infix syntax is provided for all of these type classes by the fs2.util.syntax object, which is used by
adding import fs2.util.syntax._
. The infix syntax has no runtime cost. The type classes generally do
not define many derived methods (with the exception of Async
). Instead, derived methods are defined soley infix.
For example, Monad
does not define flatten
but monad infix syntax does.
Note that these type classes are intentionally minimal. Providing a general purpose set of functional structures is not a goal of FS2.