Scala 尝试创建一个泛型函数来对树的元素求和

Scala 尝试创建一个泛型函数来对树的元素求和,scala,generics,Scala,Generics,我正在使用这里定义的树 在哪里 class Tree[+T] case object Empty extends Tree[Nothing] case class Node[T](val elem: T, val left: Tree[T], val right: Tree[T]) extends Tree[T] 我加上了这个特点 trait sum[T] { def +(value: T): T } 我定义了这棵树 val a = Node(1, Node(1, Empty, No

我正在使用这里定义的树

在哪里

class Tree[+T]
case object Empty extends Tree[Nothing] 
case class Node[T](val elem: T, val left: Tree[T], val right: Tree[T]) extends Tree[T]
我加上了这个特点

trait sum[T] {
  def +(value: T): T
}
我定义了这棵树

val a = Node(1, Node(1, Empty, Node(5, Empty, Empty)), Node(2, Node(3, Empty, Empty), Empty))
然后我写了这个函数来总结元素

def sumTree[T <: sum[T]](t: Tree[T]): T = t match {
    case Empty => 0
    case Node(e, left, right) => e + sumTree(left) + sumTree(right)
}
def sumTree[T 0
案例节点(e,左,右)=>e+sumTree(左)+sumTree(右)
}
问题

1) 为什么我必须定义一个trait(假设我已经正确定义了它)来使用“+”?如果没有它,编译器会将其视为试图连接字符串


2) 我不知道如何处理“空”。我想处理“空”模式匹配时为0,但由于泛型处理,我不能。是因为我不能使用泛型处理吗?我必须事先指定它接受/返回的类型?

因为元素类型
t
是泛型的,所以需要提供一个帮助器结构来处理加法。Scala不知道如何添加两个元素类型为
T
,没有进一步的信息。这就是为什么你定义了一个trait
sum
。正如你正确怀疑的那样,你还需要一种方法来知道零元素是什么。所以你更愿意使用这样的方法:

trait Sum[T] {
  def zero: T
  def plus(x: T, y: T): T
}

请注意,我们用两个操作数定义了
plus
。然后不再需要
T谢谢!如果我想继续使用trait呢?在这种情况下我将如何使用zero/plus?我得到了一个无法解析zero/plus的错误。您可以将
zero
添加到原始trait,比如
trait sum[T]{def zero:T;def+(value:T):T}
,但它没有多大意义,因为它与当前表示的值无关……而且,您的
sumTree
方法需要
T
类型的值才能访问
zero
。或者您编写
def sumTree>T好的,谢谢。坚持这个特点似乎有点混乱,所以我会用数字
def sumTree[T](t: Tree[T])(implicit num: Numeric[T]): T = t match {
  case Empty => num.zero
  case Node(e, left, right) => 
    num.plus(e, num.plus(sumTree(left), sumTree(right)))
}
def sumTree[T](t: Tree[T])(implicit num: Numeric[T]): T = t match {
  case Empty => num.zero
  case Node(e, left, right) => 
    import num.mkNumericOps
    e + sumTree(left) + sumTree(right)
}