Lazy handler for Amb
atennapel opened this issue · comments
Albert ten Napel commented
Is there a way to implement a handler similar to ambList
that returns a stream, lazily returning the results?
My naive attempt did not work, but will result in an infinite loop:
def ambStream[R](prog: Amb => Control[R]): Control[Stream[R]] =
new Handler[Stream[R]] with Amb {
def flip() = use { resume =>
for {
x <- resume(true)
y <- resume(false)
} yield x ++ y
}
} handle { amb => prog(amb).map(Stream(_)) }
def flip(implicit amb: Amb): Control[Boolean] = amb.flip()
def from(n: Int)(implicit amb: Amb): Control[Int] = for {
x <- flip
y <- if (x) pure(n) else from(n + 1)
} yield y
Jonathan Immanuel Brachthäuser commented
I think the easiest way is to define your own Stream, where the tail is an unforced computation (that is, in Control
), like:
sealed trait Stream[T]
case class Halt[T]() extends Stream[T]
case class Emit[T](head: T, tail: Control[Stream[T]]) extends Stream[T]
Probably for your use-case, you might even want
case class Append[T](init: Control[Stream[T]], tail: Control[Stream[T]]) extends Stream[T]
to not having to force the init.