2015-09-14 63 views
0

我在Scala中實現一個不可變BST時遇到了一些麻煩。這個問題似乎是由於某些原因,儘管我已經將K定義爲Ordered[K](第二行),但實際上它正在被Scala編譯器考慮爲Any。爲什麼?在Scala中訂購編譯錯誤

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

編譯器似乎是由你告訴它的泛型類型KOrdered[K]亞型混淆。我也有點困惑。這就像說,AList[A]的子類型,我無法將頭圍住。一個類型如何成爲該類型列表的子類型?在某些情況下,遞歸定義類型可能有用,但我不認爲這是其中之一。

從上下文來看,我覺得你想要的實際語法是[K: Ordered]。這告訴編譯器期望在範圍內存在隱含的Ordered[K]的通用類型K。這是語法糖,改變你的Node類是這樣的:

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

嗯?在Java中,我只想說K延伸了Comparable 並且沒有混淆。 –

0

這是因爲在JVM的類型擦除 - 斯卡拉擦除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 
+0

隱式參數需要在新的參數列表中。你需要......,右:BST)(隱式cmp:排序[K])'。 –

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) 
    } 
} 
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) 
    } 
} 

這個編譯和按預期工作。