---
title: Std.Stream
---

Lazy, pull-based, possibly-infinite sequences built on first-class continuations.

## Types

### Stream

```saga
type Stream a =
  | Stream (Unit -> Step a)
```

A lazy sequence. Pull from it by forcing the inner thunk via `next`,
or use the combinators below.

## Effects

### Gen

```saga
effect Gen a {
  fun yield : a -> Unit
}
```

Producer effect. A function that performs `yield!` can be turned into
a Stream via `from_gen`.

## Handlers

### stream_of

```saga
handler stream_of for Gen a
```

Handler that converts a Gen-style producer into a Stream. Each `yield!`
captures the continuation and packages it as the next Stream cell.

## Functions

### from_gen

```saga
fun from_gen : Unit -> Unit needs {Gen a} -> Stream a
```

Build a Stream from a generator function that uses the Gen effect.

Example:
fun nats_from : Int -> Unit needs {Gen Int}
nats_from n = { yield! n; nats_from (n + 1) }

let nats = Stream.from_gen (fun () -> nats_from 0)

### empty

```saga
fun empty : Unit -> Stream a
```

The empty stream.

### singleton

```saga
fun singleton : a -> Stream a
```

A stream that yields a single value, then ends.

### from_list

```saga
fun from_list : List a -> Stream a
```

Convert a list into a stream.

### repeat

```saga
fun repeat : a -> Stream a
```

An infinite stream that yields the same value forever.

### iterate

```saga
fun iterate : a -> a -> a -> Stream a
```

An infinite stream produced by repeatedly applying `f` to the previous value.
`iterate f x` yields x, f x, f (f x), ...

### range

```saga
fun range : Int -> Int -> Stream Int
```

A finite stream of integers from `lo` (inclusive) to `hi` (exclusive).

### range_from

```saga
fun range_from : Int -> Stream Int
```

An infinite stream of integers starting at `lo`.

### next

```saga
fun next : Stream a -> Maybe (a, Stream a)
```

Pull the next element. Returns `Nothing` if the stream is exhausted,
or `Just (value, rest)` if a value is available.

### is_empty

```saga
fun is_empty : Stream a -> Bool
```

Returns True if the stream has no more elements.

### map

```saga
fun map : a -> b -> Stream a -> Stream b
```

Apply `f` to each element. Lazy: nothing is computed until pulled.

### filter

```saga
fun filter : a -> Bool -> Stream a -> Stream a
```

Keep only elements for which `p` returns True. Lazy.

### flat_map

```saga
fun flat_map : a -> Stream b -> Stream a -> Stream b
```

Map each element to a stream and concatenate the results.

### append

```saga
fun append : Stream a -> Stream a -> Stream a
```

Concatenate two streams. The second is only pulled once the first is exhausted.

### zip

```saga
fun zip : Stream a -> Stream b -> Stream (a, b)
```

Pair up two streams element-wise. Stops when either runs out.

### take

```saga
fun take : Int -> Stream a -> Stream a
```

Take the first `n` elements.

### drop

```saga
fun drop : Int -> Stream a -> Stream a
```

Skip the first `n` elements.

### take_while

```saga
fun take_while : a -> Bool -> Stream a -> Stream a
```

Take elements while `p` returns True; stop at the first False.

### drop_while

```saga
fun drop_while : a -> Bool -> Stream a -> Stream a
```

Skip elements while `p` returns True; yield the rest including the first False.

### to_list

```saga
fun to_list : Stream a -> List a
```

Materialize the stream into a list. Will not terminate on infinite streams.

### fold

```saga
fun fold : b -> a -> b -> b -> Stream a -> b
```

Left fold over the stream.

### for_each

```saga
fun for_each : a -> Unit needs {..e} -> Stream a -> Unit needs {..e}
```

Run `f` for every element, in order. The callback may use any effects.

### length

```saga
fun length : Stream a -> Int
```

Count the elements. Will not terminate on infinite streams.

