Scala 枚举值未排序?

标签 scala enums

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 =(

在最后两个语句中,第一个起作用并表明枚举值具有定义的排序。第二个报错:
could not find implicit value for evidence parameter of type (this.Dogs.Value) => Ordered[this.Dogs.Value]

我如何解决这个问题并在需要排序的通用方法中使用枚举值?

最佳答案

问题是Value工具Ordered[Enumeration#Value] , 而不是 Ordered[Dogs.Value] .我不知道这样做的理由,不可能以其他方式做到这一点。

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

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

但是,类型参数 AOrdered是不变的,所以当你要求类型参数可以查看为 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

关于Scala 枚举值未排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2360773/

相关文章:

scala - 如何使用 Play Framework 和 Scala 获取系统时间?

Scala Some、None 和我的自定义默认值

Scala 监听器/观察器

c# - 将枚举绑定(bind)到 WPF 控件(如 Combobox、TabHeader 等)的方法

java - 枚举和单例 - 顶级与嵌套枚举

c# - Automapper 将 Flags Enum 从 ViewModel 映射到域模型

java - java自动机的简单枚举

scala - 使用 vim 编辑 scala 时跳转到源代码

javascript - typescript 中的字符串枚举

java - 根据尖括号拆分字符串?