【发布时间】:2020-11-06 19:27:28
【问题描述】:
在 Essential scala 一书中,他们有一个使用泛型/类型表示树的示例。
我感到困惑的是,说这是一个 Tree[Int]。所以左/右值是节点,值是Int类型。
为什么 fold 的类型参数必须是 B 而不是 A?我很困惑为什么有 2 种类型 A 和 B 而不仅仅是类型 A,如果它是 Tree[Int],它就是 Int。
sealed trait Tree[A] {
def fold[B](node: (B, B) => B, leaf: A => B): B
}
final case class Node[A](left: Tree[A], right: Tree[A]) extends Tree[A] {
def fold[B](node: (B, B) => B, leaf: A => B): B =
node(left.fold(node, leaf), right.fold(node, leaf))
}
final case class Leaf[A](value: A) extends Tree[A] {
def fold[B](node: (B, B) => B, leaf: A => B): B =
leaf(value)
}
【问题讨论】:
-
为什么要限制自己将 Int 的 Tree 折叠成 Int,而您可以将它折叠成任何其他事物? - 让我们使用一个更简单的数据结构作为示例,您有一个 Ints 的 List,您可以将其所有元素相加,例如
list.foldLeft(0)(_ + _),或者您可以创建一个包含所有它的数字按顺序排列,如list.fold("")(_ + _.toString)- 所以你可以将foldInt 的 List 转换为 Int 或 String 或其他任何东西。 -
我很困惑为什么你需要另一个类型 B。如果 A 是 Int,你可以重复使用类型参数 A no?
-
什么?不,您需要另一种类型正是因为
A是Int。查看 Listdef foldLeft[A, B](list: List[A])(z: B)(op: (B, A) => B): B中 foldLeft 的定义,这样您就可以将列表中的所有元素组合成任何类型的单个元素B,只要您给我一个初始值即可输入B,然后您向我解释如何将B类型的值与当前A类型的值组合成另一个B类型的值。现在,在对 List 的所有元素求和的情况下,B也是 Int,但在将它们连接在一起的情况下,B是 String . -
如果
Tree是一种类型Int,而您的fold()目标是另一种类型String?,那么您需要2 个泛型来描述Int-to -String转换,即A => B。 -
所以 A 和 B 可能相同,但因为它们可能不同,所以您必须明确
标签: scala