gpt4 book ai didi

scalaz 蹦床和 IO

转载 作者:行者123 更新时间:2023-12-04 05:00:51 25 4
gpt4 key购买 nike

此问题与此其他 question 有关但简化为更简单的情况:

我假设以下进口:

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 map/flatMap 也被蹦床?似乎我在第二个内部创建了其他嵌套堆栈以供理解。我需要写一个 TrampolineT将使用 unsafePerformIO并将提取的 io 值重新包装到挂起状态?

最佳答案

所以 IO(_) 已经是 trampolined ,为了它的值(value)。除了 folone 的建议之外,我还可以通过像这样更改第二个来避免溢出:

val s = for (a <- ioa; b <- iob) yield a + b
val s1 = s.unsafePerformIO()
IO(s1)

或者像这样:
IO(for (a <- ioa; b <- iob) yield a + b).flatMap(identity)

还有 IO(_)采用按名称参数,所以 IO(expr)val e = expr; IO(e)行为不一样。这会溢出!
val s = for (a <- ioa; b <- iob) yield a + b
IO(s.unsafePerformIO())

因此,虽然这不是一个非常令人满意的答案,但似乎尽可能使用应用程序或包装在另一个 IO 中。扁平化将是解决堆栈问题的方法。

关于scalaz 蹦床和 IO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16171618/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com