この質問はこの他の質問に関連していますが、より単純なケースに縮小されています。
次のインポートを想定しています。
import scalaz._, Scalaz._
import Free._, effect._
次のジェネレーターがあります。
val fromOneIO: () => IO[Int] = {
var i = 0; () => { i += 1; IO(i) }
}
val fromOne: () => Int = {
var i = 0; () => { i += 1; i }
}
および次の非末尾再帰定義:
def rec(i: Int): Int = {
if (i == 0) {
fromOne()
} else {
rec(i - 1) + fromOne()
}
}
def rec1(i: Int): Trampoline[Int] = {
if (i == 0) {
Return(fromOne())
} else {
suspend {
for {
a <- rec1(i - 1)
b <- Return(fromOne()): Trampoline[Int]
} yield a + b
}
}
}
def recio(i: Int): Trampoline[IO[Int]] = {
if (i == 0) {
Return(fromOneIO())
} else {
suspend {
for {
ioa <- recio(i - 1)
iob <- Return(fromOneIO()): Trampoline[IO[Int]]
} yield {
for (a <- ioa; b <- iob) yield a + b
}
}
}
}
結果は次のとおりです。
rec(100) // overflows for arg 10000
rec1(10000).run // works
recio(10000).run.unsafePerformIO() //overflows
IOマップ/フラットマップもトランポリンするようにするにはどうすればよいですか? 理解のために、2番目の内部に他のネストされたスタックが作成されているようです。抽出された io 値をTrampolineT
使用してサスペンドに再ラップする を作成する必要がありますか?unsafePerformIO