Introduction to Streams
In this guide, we'll explore the concept of a Stream<R, E, A>
. 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
.
What is a Stream?
Think of a Stream
as an extension of an Effect
. While an Effect<R, E, A>
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<R, E, A>
takes this further by allowing the emission of zero or more values of type A
.
To clarify, let's examine some examples using Effect
:
import { Effect, Chunk, Option } from "effect"
// An Effect that fails with a string error
const failedEffect = Effect.fail("fail!")
// An Effect that produces a single number
const oneNumberValue = Effect.succeed(3)
// An Effect that produces a chunk of numbers
const oneListValue = Effect.succeed(Chunk.make(1, 2, 3))
// An Effect that produces an optional number
const oneOption = Effect.succeed(Option.some(1))
In each case, the Effect
always ends with exactly one value. There is no variability; you always get one result.
Understanding Streams
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:
import { Stream } from "effect"
// An empty Stream
const emptyStream = Stream.empty
// A Stream with a single number
const oneNumberValueStream = Stream.succeed(3)
// A Stream with a range of numbers from 1 to 10
const finiteNumberStream = Stream.range(1, 10)
// An infinite Stream of numbers starting from 1 and incrementing
const infiniteNumberStream = Stream.iterate(1, (n) => n + 1)
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.