///|
priv enum Stream[A] {
Empty
Cons(A, Stream[A])
Suspension(() -> Stream[A])
}
///|
fn[A] Stream::iter(self : Stream[A]) -> Iter[A] {
let mut s = self
Iter::new(() => {
for s_ = s {
match s_ {
Empty => break None
Cons(h, t) => {
s = t
break Some(h)
}
Suspension(f) => continue f()
}
}
})
}
///|
fn[A] Stream::mix(self : Stream[A], other : Stream[A]) -> Stream[A] {
match self {
Empty => other
Cons(s1, s_) => Cons(s1, s_.mix(other))
Suspension(sd) => Suspension(() => other.mix(sd()))
}
}
///|
test "mix" {
fn int_stream_from(i) {
Cons(i, Suspension(() => int_stream_from(i + 1)))
}
debug_inspect(
int_stream_from(100).mix(int_stream_from(200)).iter().take(10).to_array(),
content=(
#|[100, 200, 101, 201, 102, 202, 103, 203, 104, 204]
),
)
}
///|
/// s = (s1 s2 s3 ...)
///
/// map_fold_mix(s, f) = mix(f(s1), mix(f(s2), mix(f(s3), ...)))
fn[A] Stream::map_fold_mix(self : Stream[A], f : (A) -> Stream[A]) -> Stream[A] {
match self {
Empty => Empty
Cons(s1, s_) => f(s1).mix(s_.map_fold_mix(f))
Suspension(sd) => Suspension(() => sd().map_fold_mix(f))
}
}
///|
test "map_fold_mix" {
fn int_stream_from(i) {
Cons(i, Suspension(() => int_stream_from(i + 1)))
}
fn f(i) {
int_stream_from(i * 100)
}
let a = int_stream_from(1).map_fold_mix(f)
let a40 = a.iter().take(40).collect()
assert_true(a40.search(103) != None)
assert_true(a40.search(203) != None)
assert_true(a40.search(303) != None)
}