Scala Enumeration值未订购?

Lar*_*ken 6 enums scala

scala文档说Enumeration.Val是有序的,但是当我尝试对枚举值强制类型限制要求它们支持排序时,我会得到不一致的行为:

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 =(
Run Code Online (Sandbox Code Playgroud)

在最后两个语句中,第一个工作并显示Enumeration值具有已定义的排序.第二个给出错误:

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

我如何绕过这个并在需要排序的泛型方法中使用枚举值?

ret*_*nym 9

问题在于Value实施者Ordered[Enumeration#Value],而不是Ordered[Dogs.Value].我不知道这个的理由,不可能以其他方式做到这一点.

这对于直接比较两个值的简单情况就足够了 - 它只是一个普通的方法调用:

scala> (Rover: Ordered[Enumeration#Value]).<(Sam)
res44: Boolean = false
Run Code Online (Sandbox Code Playgroud)

但是,类型参数Ain Ordered是不变的,因此当您要求类型参数可查看时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)
Run Code Online (Sandbox Code Playgroud)

或者,通过显式传递type参数doSomething:

scala> doSomething[Enumeration#Value](List(Rover, Sam))                          
List(Sam, Rover)
Run Code Online (Sandbox Code Playgroud)

或者,更好的是,放松对类型参数的要求,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)
Run Code Online (Sandbox Code Playgroud)

为什么这样做?

scala> Rover: Ordered[_ <: Enumeration#Value]
res52: scala.math.Ordered[_ <: Enumeration#Value] = Rover
Run Code Online (Sandbox Code Playgroud)