2010-03-02 59 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