如何在Scala中使我的不可变二进制搜索树通用?

时间:2014-08-13 08:04:53

标签: scala generics binary-search-tree

我是Scala的新手。我正在尝试开发自己的不可变二叉搜索树。

首先,我开发了一个在其节点上使用Int的二叉搜索树。之后,我决定开发通用的二叉搜索树。

当我编译这些代码时,我从终端获取了这些错误消息。

trait GenericBST[+T] {

    def add[TT >: T](x: T): GenericBST[TT] = this match {
        case Empty => Branch(x, Empty, Empty)
        case Branch(d, l, r) => 
          if(d > x) Branch(d, l.add(x), r) 
          else if(d < x) Branch(d, l, r.add(x)) 
          else this   
    }
}

case class Branch[+T](x: T, left: GenericBST[T], right: GenericBST[T]) extends GenericBST[T]
case object Empty extends GenericBST[Nothing]
  

错误:值&lt;不是类型参数T的成员。

错误是明智的,我该如何解决?

别忘了我是Scala的新手,所以请详细解释一下。

1 个答案:

答案 0 :(得分:4)

T代表任何类型,但为了使用><,您需要一种有序排序的类型。

在scala中,它意味着您必须设置T类型的边界,将其限制为T存在的所有Ordering[T]。您可以使用上下文绑定,或者等效地要求ord类型的隐式Ordering[TT]

trait GenericBST[+A] {
  def add[B >: A](x: B)(implicit ord: Ordering[B]): GenericBST[B] = {
    import ord.mkOrderingOps
    this match {
      case Empty => Branch(x, Empty, Empty)
      case Branch(e, l, r) =>
        if (e > x) Branch(e, l.add(x), r)
        else if (e < x) Branch(e, l, r.add(x))
        else this
    }
  }
}

case class Branch[+A](x: A, left: GenericBST[A], right: GenericBST[A]) extends GenericBST[A]
case object Empty extends GenericBST[Nothing]

导入ord.mkOrderingOps允许使用语法

e > x

而不是

ord.gt(e, x)

您也可以直接使用上下文绑定,但是需要一些额外的工作来获取范围内的隐式ord(并且它可以说是不太可读):

def add[B >: A : Ordering](x: B): GenericBST[B] = {
  val ord = implicitly[Ordering[B]]
  import ord.mkOrderingOps
  ...
}

绝对不相关,但您可能想知道为什么我在我的示例中使用了AB,而不是TTT。根据{{​​3}}:

  

对于简单类型参数,应使用单个大写字母(来自英文字母),从A开始(这与以T开头的Java约定不同)