返回两个值中的第一个的通用方法

时间:2011-08-14 15:37:19

标签: generics scala

我需要一个方法来返回两个有序值中的第一个。我试过了:

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]。下一步是什么?

3 个答案:

答案 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 OrderedorderingToOrdered隐式转化,因此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兼容的优势,正如其他人所指出的那样,OrderedOrdering之间存在隐式转换。

答案 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)