b-studios / scala-effekt

Extensible algebraic effects with handlers

Home Page:http://b-studios.de/scala-effekt

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Lazy handler for Amb

atennapel opened this issue · comments

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

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.