我需要一个方法来返回两个有序值中的第一个。我试过了:
def first[T <: Ordered[T]](a: T, b: T) = {
a compare b match {
case -1 | 0 => a
case 1 => b
}
}
但是
scala> first(3,4)
<console>:9: error: inferred type arguments [Int] do not conform to method first's
type parameter bounds [T <: Ordered[T]]
first(3,4)
^
我想这是因为Int
需要转换为RichInt
,这是Ordered[Int]
而不是Ordered[RichInt]
。下一步是什么?
答案 0 :(得分:8)
您可以使用类型类Ordering
和上下文绑定:
def first[T : Ordering](a: T, b: T) = {
implicitly[Ordering[T]].compare(a, b) match {
case -1 | 0 => a
case 1 => b
}
}
如果您import scala.math.Ordered._
,可以进一步简化此代码。 Companion object of Ordered
有orderingToOrdered
隐式转化,因此Ordering
的所有内容也会被视为Ordered
:
import scala.math.Ordered._
def first[T : Ordering](a: T, b: T) = if (a <= b) a else b
答案 1 :(得分:8)
我认为您正在寻找视图绑定
def first[T <% Ordered[T]](a: T, b: T) = {
a compare b match {
case -1 | 0 => a
case 1 => b
}
}
然后,
scala> first(3, 2)
res3: Int = 2
在幕后,视图绑定将编译为隐式参数,将T
类型转换为Ordered[T]
。 Daniel Sobral的回答有一个很好的解释:What are Scala context and view bounds?
修改的。在Scala 2.8中引入,Ordering
可能是进行比较的首选方法,但我找不到任何明确的指导。我猜Ordered
具有与Java Comparable
兼容的优势,正如其他人所指出的那样,Ordered
和Ordering
之间存在隐式转换。
答案 2 :(得分:1)
您可以简单地使用隐式参数并使用排序方法使其更清晰:
def first[T](a: T, b: T)( implicit ord: Ordering[T] ) = {
import ord._
if( a <= b ) a else b
}
或者如果您不关心在平等的情况下返回哪一个:
def first[T](a: T, b: T)( implicit ord: Ordering[T] ) =
ord.min(a,b)