我在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)
}
答案 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)
编译器似乎对你告诉它通用类型K
是Ordered[K]
的子类型感到困惑。我也有点困惑。这就像说A
是List[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)
}
}