Scala中的Ordered编译错误

时间:2015-09-14 23:25:14

标签: scala generics

我在Scala中实现不可变的BST时遇到了一些麻烦。问题似乎是由于某些原因,虽然我已将K定义为Ordered[K](第2行),但Scala编译器实际上将其视为Any。为什么呢?

abstract class BST
sealed case class Node[K <: Ordered[K], V](key : K, value : V, left : BST, right : BST) extends BST
sealed case class Empty() extends BST

object BST {
  def empty = Empty()

  def add[K <: Ordered[K], V](key : K, value : V, tree : BST) : BST = tree match {
    case Empty() => new Node(key, value, Empty(), Empty())
    case Node(nodeKey, nodeValue, left, right) =>
      if (key < nodeKey) new Node(nodeKey, nodeValue, add(key, value, left), right)
      else if (key > nodeKey) new Node(nodeKey, nodeValue, left, add(key, value, right))
      else new Node(key, value, left, right)
  }

4 个答案:

答案 0 :(得分:1)

好的伙计们,谢谢你的帮助。但是我认为你们所做的一切都太复杂了。唯一的问题似乎是BST也必须是BST [K,V]:

abstract class BST[K <: Ordered[K], V]
sealed case class Node[K <: Ordered[K], V](key : K, value : V, left : BST[K, V], right : BST[K, V]) extends BST[K, V]
sealed case class Empty[K <: Ordered[K], V]() extends BST[K, V]

object BST {
  def empty = Empty()

  def add[K <: Ordered[K], V](key : K, value : V, tree : BST[K, V]) : BST[K, V] = tree match {
    case Empty() => new Node(key, value, Empty(), Empty())
    case Node(nodeKey, nodeValue, left, right) =>
      if (key < nodeKey) new Node(nodeKey, nodeValue, add(key, value, left), right)
      else if (key > nodeKey) new Node(nodeKey, nodeValue, left, add(key, value, right))
      else new Node(key, value, left, right)
  }
}

这会按预期编译并运行。

答案 1 :(得分:0)

编译器似乎对你告诉它通用类型KOrdered[K]的子类型感到困惑。我也有点困惑。这就像说AList[A]的子类型,我无法绕过那个。类型如何成为该类型列表的子类型?递归定义类型在某些情况下可能有效,但我不认为这是其中之一。

从上下文来看,我觉得你想要的实际语法是[K: Ordered]。这告诉编译器期望在范围内存在隐式K的泛型类型Ordered[K]。语法糖将您的Node类更改为如下所示:

sealed case class Node[K, V](key : K, value : V, left : BST, right : BST)(implicit evidence: Ordered[K]) extends BST

答案 2 :(得分:0)

这是因为JVM上的类型擦除 - 在Scala中被删除为Any。有关如何解决此问题的示例,请参阅此答案:How to pattern match on generic type in Scala?。或者考虑传递一个隐含的Ordering,如下所示:

sealed case class Node[K, V](key : K, value : V, left : BST, right : BST,
  implicit cmp: Ordering[K]) extends BST

答案 3 :(得分:0)

我已将其归结为编译版本,但它可能并不是最小的,并且可能会删除一些明确的注释。如果您需要更多解释,请发表评论。

abstract class BST[K : Ordering, V]
sealed case class Node[K : Ordering, V](key : K, value : V, left : BST[K, V], right : BST[K,V]) extends BST[K, V]
sealed case class Empty[K : Ordering, V]() extends BST[K, V]

object BST {
  def empty[K : Ordering, V] = Empty[K,V]()

  def add[K : Ordering, V](key : K, value : V, tree : BST[K,V]) : BST[K,V] = tree match {
    case Empty() => new Node(key, value, Empty(), Empty())
    case Node(nodeKey, nodeValue, left, right) =>
      if (implicitly[Ordering[K]].lt(key,  nodeKey)) new Node(nodeKey, nodeValue, add(key, value, left), right)
      else if (implicitly[Ordering[K]].gt(key,nodeKey)) new Node(nodeKey, nodeValue, left, add(key, value, right))
      else new Node(key, value, left, right)
  }
}