scalaz StreamT 的 flatMap 的堆栈安全

Stack safety of scalaz StreamT's flatMap

以下代码将流构造为由 flatMap 展平的流树。问题是在迭代结果流时它不是堆栈安全的。此代码的堆栈安全等效项是什么?

import scalaz.Id._
import scalaz.StreamT

object StreamOverflow extends App {

  def streams(branchingFactor: Int, depth: Int): StreamT[Id, Int] = {
    if(depth == 0) {
      StreamT.empty
    } else {
      StreamT.fromIterable(1 to branchingFactor) flatMap { _ =>
        streams(branchingFactor, depth-1) }
    }
  }

  streams(10, 10) foreach { _ =>  } // stack overflow
}

我正在使用 scalaz 7.2.0-RC1。

您可以使用 Trampoline 而不是 Id:

import scalaz.Id.Id
import scalaz.{ StreamT, ~> }
import scalaz.Free.Trampoline
import scalaz.syntax.applicative._

object trampolineId extends (Id ~> Trampoline) {
  def apply[A](i: A): Trampoline[A] = i.point[Trampoline]
}

def streams(branchingFactor: Int, depth: Int): StreamT[Trampoline, Int] =
  if (depth == 0) StreamT.empty else {
    StreamT.fromIterable(1 to branchingFactor).trans(trampolineId).flatMap { _ =>
      streams(branchingFactor, depth - 1)
    }
  }

现在像 streams(10, 10).foreach(_ => ().point[Trampoline]).run 这样的东西可能会 运行 很长时间,但它不应该溢出堆栈。