2010-03-02 80 views
5

斯卡拉文檔說Enumeration.Val是有序的,但我得到不一致的行爲的時候,當我試圖強制執行枚舉值類型限制,要求他們支持排序:未定購Scala枚舉值?

object Dogs extends Enumeration { 
    val Sam, Tom, Rover = Value 
} 

def doSomething[A <% Ordered[A]](a : List[A]) : Unit = { 
    println(a.sortWith(_ < _)) 
} 

import Dogs._ 

val xs = List(Rover, Tom, Sam, Sam, Rover) 

println(xs.sortWith(_ < _)) // works! 
doSomething(xs)    // fails =(

最後兩條語句,第一工作並顯示Enumeration值具有已定義的順序。第二個給出錯誤:

could not find implicit value for evidence parameter of type (this.Dogs.Value) => Ordered[this.Dogs.Value] 

如何解決此問題並在需要排序的泛型方法中使用枚舉值?

回答

8

問題是Value實現者Ordered[Enumeration#Value]而不是Ordered[Dogs.Value]。我不知道這個理由,不可能以其他方式去做。

這是足以直接比較兩個值的簡單例子 - 它只是一個普通的方法調用:在Ordered

scala> (Rover: Ordered[Enumeration#Value]).<(Sam) 
res44: Boolean = false 

然而,類型參數A是不變的,所以當你你要的類型參數可見爲Ordered[A],使用Dogs.Value <: Ordered[Enumeration#Value]是不夠的。如果A是反變量,這將被允許,但它也會導致類型推斷的其他問題。

你可以解決的問題,通過與Enumeration#Value靜態輸入列表:

scala> val xs = List[Enumeration#Value](Rover, Tom, Sam, Sam, Rover) 
xs: List[Enumeration#Value] = List(Rover, Tom, Sam, Sam, Rover) 

scala> doSomething(xs)     
List(Sam, Sam, Tom, Rover, Rover) 

或者,通過明確地傳遞類型參數doSomething

scala> doSomething[Enumeration#Value](List(Rover, Sam))       
List(Sam, Rover) 

或者更好,但鬆動對類型參數的要求,在這種情況下基本上將Ordered視爲逆變。

scala> def doSomething[A <% Ordered[_ >: A]](xs : List[A]) = xs sortWith (_ < _) 
doSomething: [A](xs: List[A])(implicit evidence$1: (A) => Ordered[_ >: A])List[A] 

scala> doSomething(List(Rover, Sam))            
res47: List[Dogs.Value] = List(Sam, Rover) 

爲什麼這會起作用?

scala> Rover: Ordered[_ <: Enumeration#Value] 
res52: scala.math.Ordered[_ <: Enumeration#Value] = Rover 
+0

謝謝@retronym,這最後一個例子解決了我的問題,雖然我的思想是從較弱的類型限制彎曲! 現在需要任何類型A,只要A可以被當作(即,或可以被轉換成)某種東西。 – 2010-03-02 22:30:24