【问题标题】:Why does a generic type class representing a Tree have A and B types?为什么表示 Tree 的泛型类型类具有 A 和 B 类型?
【发布时间】: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)
}

【问题讨论】:

  • 为什么要限制自己将 IntTree 折叠成 Int,而您可以将它折叠成任何其他事物? - 让我们使用一个更简单的数据结构作为示例,您有一个 IntsList,您可以将其所有元素相加,例如 list.foldLeft(0)(_ + _),或者您可以创建一个包含所有它的数字按顺序排列,如list.fold("")(_ + _.toString) - 所以你可以将fold IntList 转换为 IntString 或其他任何东西。
  • 我很困惑为什么你需要另一个类型 B。如果 A 是 Int,你可以重复使用类型参数 A no?
  • 什么?不,您需要另一种类型正是因为AInt。查看 List def foldLeft[A, B](list: List[A])(z: B)(op: (B, A) => B): B 中 foldLeft 的定义,这样您就可以将列表中的所有元素组合成任何类型的单个元素 B,只要您给我一个初始值即可输入B,然后您向我解释如何将B 类型的值与当前A 类型的值组合成另一个B 类型的值。现在,在对 List 的所有元素求和的情况下,B 也是 Int,但在将它们连接在一起的情况下,BString .
  • 如果Tree 是一种类型Int,而您的fold() 目标是另一种类型String?,那么您需要2 个泛型来描述Int-to -String 转换,即A => B
  • 所以 A 和 B 可能相同,但因为它们可能不同,所以您必须明确

标签: scala


【解决方案1】:

Fold 是一种将F[A] 减少为单个值B 的操作。

您当然可以将Int 的树减少为单个Int(通过添加整数,即)在这种情况下AB 将是相同的。

但是 fold 可以为你做更多的事情。你也可以将你的树折叠成一个字符串,例如打印它的结构。

Fold 比您预期的更一般。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多