Introduction to Streams
In this guide, we’ll explore the concept of a Stream<A, E, R>
. A Stream
is a program description that, when executed, can emit zero or more values of type A
, handle errors of type E
, and operates within a context of type R
.
Streams are particularly handy whenever you’re dealing with sequences of values over time. They can serve as replacements for observables, node streams, and AsyncIterables.
Think of a Stream
as an extension of an Effect
. While an Effect<A, E, R>
represents a program that requires a context of type R
, may encounter an error of type E
, and always produces a single result of type A
, a Stream<A, E, R>
takes this further by allowing the emission of zero or more values of type A
.
To clarify, let’s examine some examples using Effect
:
In each case, the Effect
always ends with exactly one value. There is no variability; you always get one result.
Now, let’s shift our focus to Stream
. A Stream
represents a program description that shares similarities with Effect
, it requires a context of type R
, may signal errors of type E
, and yields values of type A
. However, the key distinction is that it can yield zero or more values.
Here are the possible scenarios for a Stream
:
- An Empty Stream: It can end up empty, representing a stream with no values.
- A Single-Element Stream: It can represent a stream with just one value.
- A Finite Stream of Elements: It can represent a stream with a finite number of values.
- An Infinite Stream of Elements: It can represent a stream that continues indefinitely, essentially an infinite stream.
Let’s see these scenarios in action:
In summary, a Stream
is a versatile tool for representing programs that may yield multiple values, making it suitable for a wide range of tasks, from processing finite lists to handling infinite sequences.