APIStream

Stream

Reusable descriptions of a sequence.

A stream is an initial state and a step function, nothing more: building or transforming one runs nothing, and each traversal (fold, forEach, toList) starts again from the initial state. A step’s effects happen on every traversal, and a stream over a mutable source such as a Reader shares that source’s position rather than rewinding it. Resources are acquired and released by the scope that consumes the stream; stopping early runs no hidden cleanup.

Stream

type Stream a e =    { initial : b    , step : b ->{e} Maybe (a, b)    }Source

A sequence of a, whose steps perform e. The state type is hidden; open both fields with one record pattern when implementing a consumer.

Fields

initial

initial : bSource

Where every traversal starts.

step

step : b ->{e} Maybe (a, b)Source

The next element and the state after it, or Nothing at the end.

filter

filter : (a ->{e} Bool) -> Stream a e -> Stream a eSource

The elements for which predicate answers True. Each step advances past rejected elements to the next accepted one.

import Stream

Stream.toList (Stream.filter { n -> n > 1 } (Stream.fromList [3, 1, 2])) == [3, 2]

fold

fold : (a -> b ->{e} b) -> b -> Stream a e ->{e} bSource

Traverses the stream from its start, combining each element with the result so far, beginning at initial.

import Stream

Stream.fold { n total -> total + n } 0 (Stream.fromList [1, 2, 3]) == 6

forEach

forEach : (a ->{e} ()) -> Stream a e ->{e} ()Source

Traverses the stream from its start, calling action on each element for its effects.

import State
import Stream

total = State.run 0 { Stream.forEach { n -> State.put (State.get () + n) } (Stream.fromList [1, 2, 3]) }

total.state == 6

fromList

fromList : List a -> Stream a eSource

The elements of a list, in order. Its state is the rest of the list.

import Stream

Stream.toList (Stream.fromList [1, 2, 3]) == [1, 2, 3]

map

map : (a ->{e} b) -> Stream a e -> Stream b eSource

The stream of action applied to each element. action runs during traversal, once per element reached.

import Stream

Stream.toList (Stream.map { n -> n * 2 } (Stream.fromList [1, 2, 3])) == [2, 4, 6]

take

take : Int -> Stream a e -> Stream a eSource

At most the first count elements. With count zero or less, the source is never stepped.

import Stream

Stream.toList (Stream.take 2 (Stream.fromList [1, 2, 3])) == [1, 2]
Stream.toList (Stream.take 5 (Stream.fromList [1])) == [1]

toList

toList : Stream a e ->{e} List aSource

Traverses the stream from its start and collects its elements in order.

import Stream

Stream.toList (Stream.fromList ["a", "b"]) == ["a", "b"]

unfold

unfold : a -> (a ->{e} Maybe (b, a)) -> Stream b eSource

The stream that starts at initial and advances with step.

import Stream

naturals = Stream.unfold 0 { n -> Just (n, n + 1) }

Stream.toList (Stream.take 3 naturals) == [0, 1, 2]

withCursor

withCursor : Stream a e -> (Iterator a e ->{e} b) ->{e} bSource

Passes consumer an iterator at the stream’s start, for code that needs to advance by hand.

import Iterator exposing (Iterator)
import Stream

peek : Iterator Int {} -> Maybe Int
peek cursor =
    case Iterator.next cursor of
        Just (value, _) -> Just value
        Nothing -> Nothing

Stream.withCursor (Stream.fromList [7, 8]) peek == Just 7

zip

zip : Stream a e -> Stream b e -> Stream (a, b) eSource

Pairs the elements of two streams, stepping the left one before the right, and ends when either does. When the right one ends first, one unmatched left element may already have been stepped.

import Stream

Stream.toList (Stream.zip (Stream.fromList [1, 2, 3]) (Stream.fromList ["a", "b"])) == [(1, "a"), (2, "b")]