我在Scala中设置二叉树时遇到了困难。它必须是它的类型参数的协变(允许空树类型),并且其键的类型需要是Ordered的子类,以允许与其他键进行比较。这就是我到目前为止所做的:
package tutorial
class AbTree[+K <: Ordered[K],+V] {
def throwTreeException(msg:String) = throw new
Exception("TreeException: " + msg)
def replaceL[L >: K, W >: V](nTree:AbTree[L,W]): AbTree[L,W] = this match {
case ETree => throwTreeException("replaceL called on an ETree")
case tree:Tree[L,W] => tree.copy(lTree = nTree)
}
def replaceR[L >: K, W >: V](nTree:AbTree[L,W]): AbTree[L,W] = this match {
case ETree => throwTreeException("replaceR called on an ETree")
case tree:Tree[L,W] => tree.copy(rTree = nTree)
}
def insert[L >: K, W >: V](nK:L,nV:W): AbTree[L,W] = this match {
case ETree => Tree(nK,nV) //Line 18
case Tree(k,v,lT,rT) =>
if (nK < k) replaceL(lT.insert(nK,nV))
else if (nK > k) replaceR(rT.insert(nK,nV)) //Line 21
else Tree(k,v,lT,rT)
}
}
case class Tree[+K <: Ordered[K],+V]
(key:K,value:V,lTree:AbTree[K,V] = ETree,rTree:AbTree[K,V] = ETree)
extends AbTree[K,V]
case object ETree
extends AbTree[Nothing,Nothing]
在insert
之间给出了6个错误:
- Line 18: inferred type arguments [L,W] do not conform to method apply's type parameter bounds [K <: Ordered[K],V] Error occurred in an application involving default arguments.
- Line 18: type mismatch; found : L required: K Error occurred in an application involving default arguments
- Line 18: type mismatch; found : tutorial.Tree[K,V] required: tutorial.AbTree[L,W] Error occurred in an application involving default arguments.
- Line 18: type mismatch; found : W required: V Error occurred in an application involving default arguments.
- Line 20: value < is not a member of type parameter L
- Line 21: value > is not a member of type parameter L
这只是我尝试过的类型边界的一种组合。我已经遇到了很多错误,我不知道哪些是真正的问题,哪些是由其他问题引起的;所以我不知道从哪里开始。
我猜我的理解在某处有一个巨大的漏洞。有人可以指出我上面的主要问题是什么?
答案 0 :(得分:1)
以此为灵感。看一下Scala中Map的实现。键类型不是协变的,值类型是。也许定义isEmpty
方法而不是模式匹配对象更有意义。
class AbTree[K, +V](implicit ordering: Ordering[K]) {
def throwTreeException(msg:String) = throw new
Exception("TreeException: " + msg)
def replaceL[W >: V](nTree:AbTree[K, W]): AbTree[K, W] = {
val empty = AbTree.empty[K, V]
this match {
case `empty` => throwTreeException("replaceL called on an ETree")
case tree:Tree[K, W] => tree.copy(lTree = nTree)
}
}
def replaceR[W >: V](nTree:AbTree[K, W]): AbTree[K, W] = {
val empty = AbTree.empty[K, V]
this match {
case `empty` => throwTreeException("replaceR called on an ETree")
case tree:Tree[K, W] => tree.copy(rTree = nTree)
}
}
def insert[W >: V](nK:K,nV:W): AbTree[K,W] = {
val empty = AbTree.empty[K, V]
this match {
case `empty` => Tree(nK, nV) //Line 18
case Tree(k, v, lT, rT) =>
if (ordering.compare(nK, k) < 0) replaceL(lT.insert(nK, nV))
else if (ordering.compare(nK, k) > 0) replaceR(rT.insert(nK, nV)) //Line 21
else Tree(k, v, lT, rT)
}
}
}
object AbTree {
implicit private object NothingOrdering extends Ordering[Any] {
override def compare(x: Any, y: Any): Int = 0
}
private object ETree extends AbTree[Any, Nothing]
def empty[K, V]: AbTree[K, V] = ETree.asInstanceOf[AbTree[K, V]]
}
case class Tree[K, +V](key:K,
value:V,
lTree:AbTree[K,V] = AbTree.empty[K, V],
rTree:AbTree[K,V] = AbTree.empty[K, V])
(implicit ordering: Ordering[K]) extends AbTree[K,V]