gpt4 book ai didi

scala - Scala 中 Catamorphisms 的高效实现

转载 作者:行者123 更新时间:2023-12-02 03:07:13 26 4
gpt4 key购买 nike

对于表示自然数的数据类型:

sealed trait Nat
case object Z extends Nat
case class S(pred: Nat) extends Nat

在 Scala 中,这里是实现相应 catamorphism 的基本方法:

  def cata[A](z: A)(l: Nat)(f: A => A): A = l match {
case Z => z
case S(xs) => f( cata(z)(xs)(f) )
}

但是,由于对 cata 的递归调用不在尾部位置,这很容易引发堆栈溢出。

有哪些替代实现方案可以避免这种情况?我宁愿不走 F-algebras 的路除非代码最终呈现的界面看起来和上面的一样简单。

编辑:看起来这可能是直接相关的:Is it possible to use continuations to make foldRight tail recursive?

最佳答案

如果您要在列表上实现变形,那将是我们在 Haskell 中称为 foldr 的东西。我们知道 foldr 没有尾递归定义,但是 foldl 有。所以如果你坚持使用尾递归程序,正确的做法是反转列表参数(尾递归,线性时间),然后使用 foldl 代替 foldr

您的示例使用更简单的自然数数据类型(真正“高效”的实现将使用机器整数,但我们同意将其搁置一旁)。你的一个自然数的倒数是多少?只是数字本身,因为我们可以把它看成是一个列表,每个节点都没有数据,所以倒过来是分不出来的! foldl 的等价物是什么?这是程序(原谅伪代码)

  def cata(z, a, f) = {
var x = a, y = z;
while (x != Z) {
y = f(y);
x = pred(x)
}
return y
}

或者作为 Scala 尾递归,

  def cata[A](z: A)(a: Nat)(f: A => A): A = a match {
case Z => z
case S(b) => cata( f(z) )(b)(f)
}

这样行吗?

关于scala - Scala 中 Catamorphisms 的高效实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41945458/

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