Почему я получаю «Не удалось найти неявное значение для параметра ord: scala.math.Ordering [T]» - PullRequest
2 голосов
/ 26 января 2011

У меня есть простой пример черты, которая имеет значение некоторого универсального типа, произошедшего от Ordered. Я не могу найти какой-либо способ на самом деле использовать значение, хотя, как я получаю «Не удалось найти неявное значение для параметра ord: scala.math.Ordering [T]». Вот код:

trait Example[T <: Ordered[_]] {
  val key: T

  def before(that: Example[T]): Boolean = (key < that.key)    
}

Есть идеи, почему это не компилируется?

Ответы [ 2 ]

6 голосов
/ 26 января 2011

выглядит так, как должно быть

trait Example[T <: Ordered[T]] {
1 голос
/ 27 января 2011

Я полагаю, я не компилирую, потому что вы говорите, что T должен быть заказан для любого типа.Мы можем написать эквивалентную черту наподобие этой (пожалуйста, поправьте меня, если я ошибаюсь - я не уверен, можно ли ее считать эквивалентной, но по крайней мере вы получите ту же ошибку от компилятора):

trait Example1[A, T <: Ordered[A]] {
    val key: T

    def before(that: Example1[A, T]): Boolean = (key < that.key)
}

Если вы посмотрите в определение черты Ordered, вы найдете что-то вроде этого:

trait Ordered[A] extends java.lang.Comparable[A] {
  ...

  def <  (that: A): Boolean = (this compare that) <  0
  ...
}

object Ordered {  
  /** Lens from Ordering[T] to Ordered[T] */
  implicit def orderingToOrdered[T](x: T)(implicit ord: Ordering[T]): Ordered[T] = 
    new Ordered[T] { def compare(that: T): Int = ord.compare(x, that) }
}

Когда мы будем думать в терминах этого определения - если key равно Ordered[A], чем that.key должен иметь тип A (согласно < сигнатуре метода).Таким образом, компилятор не может использовать его на Ordered[A] или другими словами T.И если я не ошибаюсь, он пытается найти Ordering[T] (в соответствии с неявным определением в объекте-компаньоне), который можно использовать в качестве крайней меры (но он не работает).

Так что, если вы определите параметр типаT как T <: Ordered[T] он будет скомпилирован.

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

abstract class Example[T: Ordering] {
  val key: T
  val ord = implicitly[Ordering[T]]
  import Ordered._

  def before(that: Example[T]): Boolean = key < that.key
}

var one = new Example[Int] {val key = 1}
var two = new Example[Int] {val key = 2}

println(one.before(two)) // prints: true
println(two.before(one)) // prints: false

В этом случае неявное преобразование будет фактическииспользуется потому, что у нас есть доказательства того, что Ordering[T] существует (черты не могут иметь контекст или границы представления, поэтому я создал абстрактный класс)

Имеет ли это смысл?Если вы обнаружите недостатки в моей логике - пожалуйста, прокомментируйте!(Я буду признателен за это)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...