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.
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")]
