gpt4 book ai didi

Scalaz 的 traverse_ 与 IO monad

转载 作者:行者123 更新时间:2023-12-04 15:26:12 27 4
gpt4 key购买 nike

我想使用 IO monad。

但是这段代码不能用大文件运行。
我收到 StackOverflowError。
我试过 -DXss选项,但它会引发相同的错误。

val main = for {
l <- getFileLines(file)(collect[String, List]).map(_.run)
_ <- l.traverse_(putStrLn)
} yield ()

我该怎么做?

我写了 Iteratee 输出所有元素。
def putStrLn[E: Show]: IterV[E, IO[Unit]] = {
import IterV._
def step(i: IO[Unit])(input: Input[E]): IterV[E, IO[Unit]] =
input(el = e => Cont(step(i >|> effects.putStrLn(e.shows))),
empty = Cont(step(i)),
eof = Done(i, EOF[E]))
Cont(step(mzero[IO[Unit]]))
}
val main = for {
i <- getFileLines(file)(putStrLn).map(_.run)
} yield i.unsafePerformIO

这也是同样的结果。

我认为是由IO实现引起的。

最佳答案

这是因为 scalac 没有优化 loop getReaderLines 用于尾调用。 loop是尾递归,但我认为 case匿名函数语法妨碍了。

编辑 :实际上它甚至不是尾递归(在 IO monad 中的包装)在递归调用之后至少会导致再调用一次。当我昨天进行测试时,我使用了类似的代码,但是我删除了 IO monad,然后可以使 Iteratee 尾递归。下面的文本,假设没有 IO monad ...

我昨天在试验迭代器时碰巧发现了这一点。我想改变loop的签名这样做会有所帮助(所以暂时你可能需要重新实现 getFilesLinesgetReaderLines :

@annotations.tailrec
def loop(it: IterV[String, A]): IO[IterV[String, A]] = it match {
// ...
}

我们可能应该向 scalaz 人员报告这个问题(并且可能会为 scala 开一张增强票)。

这显示了会发生什么(代码与 getReaderLines.loop 有点相似):
@annotation.tailrec
def f(i: Int): Int = i match {
case 0 => 0
case x => f(x - 1)
}
// f: (i: Int)Int

@annotation.tailrec
def g: Int => Int = {
case 0 => 0
case x => g(x - 1)
}
/* error: could not optimize @tailrec annotated method g:
it contains a recursive call not in tail position
def g: Int => Int = {
^
*/

关于Scalaz 的 traverse_ 与 IO monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7633609/

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