Chunk represents a strict, in-memory sequence of A
values.
A pipe is a stream transformation, represented as a function from stream to stream.
A pipe is a stream transformation, represented as a function from stream to stream.
Pipes are typically applied with the through
operation on Stream
.
A Pipe2
is a stream transformation that combines two streams in to a single stream, represented as a function from stream to stream.
A Pipe2
is a stream transformation that combines two streams in to a single stream, represented as a function from stream to stream.
Pipe2
s are typically applied with the through2
operation on Stream
.
Laws:
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
Marker trait.
Marker trait. A Stream[Pure,O]
can be safely cast to a Stream[Nothing,O]
,
but the 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.
Future that evaluates to a value of type A
and a Scope[F,Unit]
.
Future that evaluates to a value of type A
and a Scope[F,Unit]
.
To use a Future
, convert to a Pull
(via f.pull
) or a Stream
(via f.stream
).
A sink is a pipe that converts a stream to a Stream[F,Unit]
.
A sink is 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
, which may evaluate F
effects.
A stream producing output of type O
, which may evaluate F
effects. If F
is Nothing
or fs2.Pure
, the stream is pure.
Laws (using infix syntax):
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
f >=> emit == f
(f >=> g) >=> h == f >=> (g >=> h)
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
Task
is a trampolined computation producing an A
that may
include asynchronous steps.
Task
is a 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 the scala.concurrent.Future
type introduced in scala 2.10,
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
or
Future.apply
. This means that Future
achieves much better thread
reuse than the 2.10 implementation and avoids needless thread
pool submit cycles.
Task
also differs from the scala.concurrent.Future
type 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.