【发布时间】:2017-01-03 09:32:46
【问题描述】:
我正在尝试为二叉树找到尾递归折叠函数。给定以下定义:
// From the book "Functional Programming in Scala", page 45
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
实现一个非尾递归函数非常简单:
def fold[A, B](t: Tree[A])(map: A => B)(red: (B, B) => B): B =
t match {
case Leaf(v) => map(v)
case Branch(l, r) =>
red(fold(l)(map)(red), fold(r)(map)(red))
}
但现在我正在努力寻找一个尾递归折叠函数,以便可以使用注解@annotation.tailrec。
在我的研究中,我发现了几个例子,其中树上的尾递归函数可以例如使用自己的堆栈计算所有叶子的总和,然后基本上是List[Tree[Int]]。但据我所知,在这种情况下,它仅适用于加法,因为您首先评估运算符的左侧还是右侧并不重要。但对于广义的折叠,它是非常相关的。为了展示我的意图,这里有一些示例树:
val leafs = Branch(Leaf(1), Leaf(2))
val left = Branch(Branch(Leaf(1), Leaf(2)), Leaf(3))
val right = Branch(Leaf(1), Branch(Leaf(2), Leaf(3)))
val bal = Branch(Branch(Leaf(1), Leaf(2)), Branch(Leaf(3), Leaf(4)))
val cmb = Branch(right, Branch(bal, Branch(leafs, left)))
val trees = List(leafs, left, right, bal, cmb)
基于这些树,我想使用给定的折叠方法创建一个深层副本,例如:
val oldNewPairs =
trees.map(t => (t, fold(t)(Leaf(_): Tree[Int])(Branch(_, _))))
然后证明平等的条件适用于所有创建的副本:
val conditionHolds = oldNewPairs.forall(p => {
if (p._1 == p._2) true
else {
println(s"Original:\n${p._1}\nNew:\n${p._2}")
false
}
})
println("Condition holds: " + conditionHolds)
有人可以指点一下吗?
您可以在 ScalaFiddle 找到此问题中使用的代码:https://scalafiddle.io/sf/eSKJyp2/15
【问题讨论】:
标签: scala tree binary-tree tail-recursion fold