Wie vermeide ich einen Stapelüberlauf, wenn ich die kostenlose Monade von scalaz verwende?

Ich hatte vorher gedacht, dass ein Teil des Ziels der Implementierung darin besteht, genau dieses Problem zu vermeiden, also mache ich vielleicht etwas offensichtlich Dummes?

Hier ist ein Code:

    // Stack overflow
import scalaz._

sealed trait Command[T]
case class Wait(ms: Long) extends Command[Unit]

case object Evaluator extends (Command ~> Id.Id) {
  override def apply[T](cmd: Command[T]) = cmd match {
    case Wait(t)  => Thread.sleep(t)
  }
}

object Api {
  def sleep(ms: Long): Free.FreeC[Command, Unit] = Free.liftFC(Wait(ms))
}

val sleep: Free.FreeC[Command, Unit] =
  Api.sleep(1).flatMap { _ => sleep }

Free.runFC(sleep)(Evaluator)

Hinweis: Mir ist klar, dass das albern ist :) In der Praxis hat meine Befehlsklasse viele Befehle, und ich habe einen Befehl, der dieselbe Schleife ausführt ... im Grunde genommen frage einen Zustand ab, wenn wahr, brich ab, wenn falsch, warte weiter.

Ich möchte den Stapelüberlauf vermeiden, den dies verursacht ... Ich dachte, dies war bereits trampoliniert, aber ich denke, ich muss es erneut manuell tun? Gibt es eine saubere Möglichkeit, dies innerhalb der freien Monadischen Denkweise zu tun?

Aktualisieren

Wenn ich weiter darüber nachdenke, denke ich, dass das Problem nicht die schlaffreie Monade ist, sondern die Id.Id-Monade, in die wir uns bei der Bewertung einbinden ... also habe ich Folgendes versucht:

case object Evaluator2 extends (Command ~> ({ type t[x] = Free[Id.Id, x] })#t) {
  override def apply[T](cmd: Command[T]) = cmd match {
    case Wait(t)  => Thread.sleep(t); Free.liftF[Id.Id, Unit](())
  }
}

Free.runFC[Command, ({ type t[x] = Free[Id.Id, x] })#t, Unit](sleep)(Evaluator2)(Free.freeMonad[Id.Id])

Aber das Problem dabei ist, dass es nur einen Schritt auswertet. Im Idealfall möchte ich, dass runFC blockiert, bis eine Bedingung erfüllt ist (oder in diesem Fall eine Endlosschleife ausführt, bis ich es beende, aber ohne Stapelüberlauf).

Antworten auf die Frage(4)

Ihre Antwort auf die Frage