Общий метод для возврата первого из двух значений

Мне нужен метод, чтобы вернуть первое из двух упорядоченных значений. Я пробовал:

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 ответа

Решение

Вы можете использовать тип класса 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._, Сопутствующий объектOrdered имеет orderingToOrdered неявное преобразование, так что все, что имеет Ordering также будет рассматриваться как Ordered:

import scala.math.Ordered._

def first[T : Ordering](a: T, b: T) = if (a <= b) a else b

Я думаю, что вы ищете вид, связанный

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], Ответ Даниэля Собрала имеет хорошее объяснение: каковы границы Scala и границы просмотра?

Редактировать Введенный в Scala 2.8, Ordering может быть предпочтительным способом сравнения, но я не смог найти каких-либо четких указаний. Похоже Ordered имеет преимущество совместимости с Java Comparableи, как отмечали другие, существуют неявные преобразования между Ordered а также Ordering,

Вы можете просто использовать неявные параметры и методы упорядочения, чтобы сделать его более понятным:

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)
Другие вопросы по тегам