fs2
package fs2
Type members
Classlikes
Strict, finite sequence of values that allows index-based random access of elements.
Chunks can be created from a variety of collection types using methods on the Chunk companion(e.g.,
Chunk.vector, Chunk.seq, Chunk.array). Additionally, the Chunk companiondefines 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.Bytesand then access the array directly.
The operations on
intermediate chunks being created (1 per call to
Chunk are all defined strictly. For example, c.map(f).map(g).map(h) results inintermediate chunks being created (1 per call to
map).- Companion
- object
Supports building a result of type
Out from zero or more Chunk[A].This is similar to the standard library collection builders but optimized for
building a collection from a stream.
building a collection from a stream.
The companion object provides implicit conversions (methods starting with
which adapts various collections to the
supports),which adapts various collections to the
Collector trait.- Companion
- object
final class CompositeFailure(val head: Throwable, val tail: NonEmptyList[Throwable]) extends Throwable
Represents multiple (>1) exceptions were thrown.
- Companion
- object
Supports treating a linear sequence of resources as a single resource.
A
a lifetime that is scoped by the
can be swapped in to the
is returned and is finalized when the
call to
Hotswap[F, R] instance is created as a Resource and hence, hasa lifetime that is scoped by the
Resource. After creation, a Resource[F, R]can be swapped in to the
Hotswap by calling swap. The acquired resourceis returned and is finalized when the
Hotswap is finalized or upon the nextcall to
swap, whichever occurs first.For example, the sequence of three resources
following diagram:
r1, r2, r3 are shown in thefollowing diagram:
{{{
----- swap(r1) ---- swap(r2) ---- swap(r3) ----X
| | | | |
Creation | | | |
r1 acquired | | |
r2 acquired | |
r1 released r3 acquired |
r2 released |
r3 released
}}}
This class is particularly useful when working with pulls that cycle through
resources -- e.g., writing bytes to files, rotating files every N bytes or M seconds.
Without
or at least an internal resource reference accumulates. With
instance is the only registered resource and each file is swapped in to the
resources -- e.g., writing bytes to files, rotating files every N bytes or M seconds.
Without
Hotswap, such pulls leak resources -- on each file rotation, a file handleor at least an internal resource reference accumulates. With
Hotswap, the Hotswapinstance is the only registered resource and each file is swapped in to the
Hotswap.Usage typically looks something like:
{{{
Stream.resource(Hotswap(mkResource)).flatMap { case (hotswap, r) =>
// Use r, call hotswap.swap(mkResource) as necessary
}
}}}
Stream.resource(Hotswap(mkResource)).flatMap { case (hotswap, r) =>
// Use r, call hotswap.swap(mkResource) as necessary
}
}}}
See
fs2.io.file.writeRotate for an example of usage.- Companion
- object
A
result of type
p: Pull[F,O,R] reads values from one or more streams, returns aresult 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.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 graiseError is caught by handleErrorWith:-
handleErrorWith(raiseError(e))(f) == f(e)- Companion
- object
@implicitNotFound("Cannot find an implicit value for RaiseThrowable[${F}]: an instance is available for any F which has an ApplicativeError[F, Throwable] instance or for F = Fallible. If getting this error for a non-specific F, try manually supplying the type parameter (e.g., Stream.raiseError[IO](t) instead of Stream.raiseError(t)). If getting this error when working with pure streams, use F = Fallible.")
Witnesses that
F supports raising throwables.An instance of
is available for the uninhabited type
RaiseThrowable is available for any F which has anApplicativeError[F, Throwable] instance. Alternatively, an instanceis available for the uninhabited type
Fallible.- Companion
- object
Represents a period of stream execution in which resources are acquired and released.
Note: this type is generally used to implement low-level actions that manipulate
resource lifetimes and hence, isn't generally used by user-level code.
resource lifetimes and hence, isn't generally used by user-level code.
- Companion
- object
A stream producing output of type
O and which may evaluate F effects.-
'''Purely functional''' a value of type
Stream[F, O]describes an effectful computation.
A function that returns aStream[F, O]builds a description of an effectful computation,
but does not perform them. The methods of theStreamclass derive new descriptions from others.
This is similar to how effect types likecats.effect.IOandmonix.Taskbuild descriptions of
computations. -
'''Pull''': to evaluate a stream, a consumer pulls its values from it, by repeatedly performing one pull step at a time.
Each step is aF-effectful computation that may yield someOvalues (or none), and a stream from which to continue pulling.
The consumer controls the evaluation of the stream, which effectful operations are performed, and when. -
'''Non-Strict''': stream evaluation only pulls from the stream a prefix large enough to compute its results.
Thus, although a stream may yield an unbounded number of values or, after successfully yielding several values,
either raise an error or hang up and never yield any value, the consumer need not reach those points of failure.
For the same reason, in general, no effect inFis evaluated unless and until the consumer needs it. -
'''Abstract''': a stream needs not be a plain finite list of fixed effectful computations in F.
It can also represent an input or output connection through which data incrementally arrives.
It can represent an effectful computation, such as reading the system's time, that can be re-evaluated
as often as the consumer of the stream requires.
=== Special properties for streams ===
There are some special properties or cases of streams:
- A stream is '''finite''', or if we can reach the end after a limited number of pull steps,
which may yield a finite number of values. It is '''empty''' if it terminates and yields no values.
- A '''singleton''' stream is a stream that ends after yielding one single value.
- A '''pure''' stream is one in which the
- A '''never''' stream is a stream that never terminates and never yields any value.
- A stream is '''finite''', or if we can reach the end after a limited number of pull steps,
which may yield a finite number of values. It is '''empty''' if it terminates and yields no values.
- A '''singleton''' stream is a stream that ends after yielding one single value.
- A '''pure''' stream is one in which the
F is Pure, which indicates that it evaluates no effects.- A '''never''' stream is a stream that never terminates and never yields any value.
== Pure Streams and operations ==
We can sometimes think of streams, naively, as lists of
This is particularly true for '''pure''' streams, which are instances of
We can convert every ''pure and finite'' stream into a
Also, we can convert pure ''infinite'' streams into instances of the
O elements with F-effects.This is particularly true for '''pure''' streams, which are instances of
Stream which use the Pure effect type.We can convert every ''pure and finite'' stream into a
List[O] using the .toList method.Also, we can convert pure ''infinite'' streams into instances of the
Stream[O] class from the Scala standard library.A method of the
in that their signature includes no type-class constraint (or implicit parameter) on the
Pure methods in
that we can applying the stream's method and converting the result to a list gets the same result as
first converting the stream to a list, and then applying list methods.
Stream class is '''pure''' if it can be applied to pure streams. Such methods are identifiedin that their signature includes no type-class constraint (or implicit parameter) on the
F method.Pure methods in
Stream[F, O] can be projected ''naturally'' to methods in the List class, which meansthat we can applying the stream's method and converting the result to a list gets the same result as
first converting the stream to a list, and then applying list methods.
Some methods that project directly to list are
There are other methods, like
but their stream counterparts return an (either empty or singleton) stream.
Other methods, like
map, filter, takeWhile, etc.There are other methods, like
exists or find, that in the List class they return a value or an Option,but their stream counterparts return an (either empty or singleton) stream.
Other methods, like
zipWithPrevious, have a more complicated but still pure translation to list methods.== Type-Class instances and laws of the Stream Operations ==
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 chunk:-
s.cons(c) == Stream.chunk(c) ++ sStream.raiseError propagates until being caught by handleErrorWith:-
Stream.raiseError(e) handleErrorWith h == h(e)-
Stream.raiseError(e) ++ s == Stream.raiseError(e)-
Stream.raiseError(e) flatMap f == Stream.raiseError(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 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 ++ b) flatMap f == (a flatMap f) ++ (b flatMap f)-
Stream.empty flatMap f == Stream.empty== Technical notes==
''Note:'' since the chunk structure of the stream is observable, and
the right identity law uses a weaker notion of equality,
normalizes both sides with respect to chunk structure:
s flatMap Stream.emit produces a stream of singleton chunks,the right identity law uses a weaker notion of equality,
=== whichnormalizes 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.flatMap(Stream.emit), which justproduces a singly-chunked stream from any input stream
s.For instance, for a stream
- the result of
- the result of
The latter is using the definition of
s and a function f: A => B,- the result of
s.map(f) is a Stream with the same chunking as the s; wheras...- the result of
s.flatMap(x => S.emit(f(x))) is a Stream structured as a sequence of singleton chunks.The latter is using the definition of
map that is derived from the Monad instance.This is not unlike equality for maps or sets, which is defined by which elements they contain,
not by how these are spread between a tree's branches or a hashtable buckets.
However, a
so two streams "equal" under that notion may give different results through this method.
not by how these are spread between a tree's branches or a hashtable buckets.
However, a
Stream structure can be observed through the chunks method,so two streams "equal" under that notion may give different results through this method.
''Note:'' For efficiency
chunk at a time and preserves chunk structure, which differs from
the
which would produce singleton chunk. In particular, if
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.
[[Stream.map]] function operates on an entirechunk at a time and preserves chunk structure, which differs from
the
map derived from the monad (s map f == s flatMap (f andThen Stream.emit))which would produce singleton chunk. In particular, if
f throws errors, thechunked 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.
- Companion
- object
@deprecated("Use fs2.compression instead", "2.3.0")
object compress
Provides utilities for compressing/decompressing byte streams.
object text
Provides utilities for working with streams of text (e.g., encoding byte streams to strings).
Types
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.
represented as a function from two streams to a single stream.
Pipe2s are typically applied with the through2 operation on Stream.