Scala cats trampoline



noel welsh和dave gurnell pag.254(" d.4 d.4更安全的折叠(,test(" ok"(是从书本的"带猫的scala"复制的"(,代码正常运行,这是蹦床foldright

import cats.Eval
test("ok") {
val list = (1 to 100000).toList

def foldRightEval[A, B](as: List[A], acc: Eval[B])(fn: (A, Eval[B]) => Eval[B]): Eval[B] =
  as match {
    case head :: tail =>
      Eval.defer(fn(head, foldRightEval(tail, acc)(fn)))
    case Nil =>
      acc
  }
def foldRight[A, B](as: List[A], acc: B)(fn: (A, B) => B): B =
  foldRightEval(as, Eval.now(acc)) { (a, b) =>
    b.map(fn(a, _))
  }.value
val res = foldRight(list, 0L)(_ + _)
assert(res == 5000050000l)
}

测试(" ko"(返回小列表的相同测试值(" ok"(,但对于长列表,该值是不同的。为什么?

test("ko") {
val list = (1 to 100000).toList
def foldRightSafer[A, B](as: List[A], acc: B)(fn: (A, B) => B): Eval[B] = as match {
  case head :: tail =>
    Eval.defer(foldRightSafer(tail, acc)(fn)).map(fn(head, _))
  case Nil => Eval.now(acc)
}
val res = foldRightSafer(list, 0)((a, b) => a + b).value
assert(res == 5000050000l)
}

这是 @olegpyzhcov的评论,转换为社区Wiki答案

您忘记了0L中的L作为第二个参数传递给foldRightSafer。因此,调用的推断通用类型为

foldRightSafer[Int, Int]((list : List[Int]), (0: Int))((_: Int) + (_: Int))

因此,您的加入溢出,并给您一些小于20000000的东西(9个零,Int.MaxValue = 2147483647(。

最新更新