Невозможно обеспечить неявное преобразование из DateTime в упорядоченный, используя неявное преобразование в Comparable - PullRequest
8 голосов
/ 13 января 2011

Я пытаюсь использовать> =,> и т. Д. С DateTime (joda), и единственный способ заставить его работать - использовать это неявное преобразование

implicit def dateTime2ordered(x: DateTime): Ordered[DateTime] =
new Ordered[DateTime] with Proxy {
  val self = x

  def compare(y: DateTime): Int = {
    x.compareTo(y)
  }
}

Я бы предпочел более общую форму, такую ​​как

implicit def comparable2ordered[A <: Comparable[A]](x: A): Ordered[A] =
    new Ordered[A] with Proxy {
      val self = x

      def compare(y: A): Int = {
        x.compareTo(y)
      }
    } 

Но компилятор не может найти это преобразование, и после попытки вызвать его напрямую я получил следующее сообщение о том, что DateTime не относится к типу Comparable [A]. После проверки источника для DateTime я увидел, что он реализует только Comparable как необработанный тип.

Я смог заставить его работать, используя

 implicit def comparable2ordered[A <: Comparable[_]](x: A): Ordered[A] =
    new Ordered[A] with Proxy {
      val self = x

      def compare(y: A): Int = {
        x.compareTo(y)
      }
    } 

У меня такой вопрос: является ли это правильное решение этой проблемы в Scala, или же связанные с подстановочными знаками типы вызовут будущие проблемы с проверкой типов?

Ответы [ 3 ]

7 голосов
/ 30 июня 2013

Я наткнулся на этот вопрос, потому что я тоже хотел сравнить объекты joda DateTime с использованием реляционных операторов.

Ответ Даниэля указал мне правильное направление: импликации, присутствующие в scala.math.Ordered, преобразуют экземплярот A extends java.lang.Comparable[A] до Ordered[A] - их просто нужно ввести в сферу применения.Самый простой способ сделать это (который я выучил здесь , кстати), это метод implicitly:

val aOrdering = implicitly[Ordering[A]]
import aOrdering._

Уловка в том, что org.joda.time.DateTime не расширяет и не реализуетComparable сам по себе, он наследует (косвенно) от org.joda.time.ReadableInstant, который делает расширяет Comparable.Так что это:

val dateTimeOrdering = implicitly[Ordering[DateTime]]
import dateTimeOrdering._

не скомпилируется, потому что DateTime не расширяет Comparable[DateTime].Чтобы использовать Ordered реляционные операторы на DateTime, вы должны сделать это вместо этого:

val instantOrdering = implicitly[Ordering[ReadableInstant]]
import instantOrdering._

, который работает, потому что ReadableInstant расширяет Comparable[ReadableInstant], а неявные преобразования в Orderedможно преобразовать его в Ordered[ReadableInstant].

Пока все хорошо.Однако бывают ситуации, когда Ordered[ReadableInstant] недостаточно хорош.(Я столкнулся с тем, что ScalaTest на больше и меньше, чем Matchers .) Чтобы получить Ordered[DateTime], я был вынужден сделать следующее:

implicit object DateTimeOrdering extends Ordering[DateTime] {
  def compare(d1: DateTime, d2: DateTime) = d1.compareTo(d2)
}

Кажется, чтобыло бы проще, но я не мог понять это.

3 голосов
/ 13 января 2011

Хорошо, необработанный тип «Comparable» переводится как «Comparable [_]» в Scala.

Они называются экзистенциальными типами, Comparable [_] - это сокращение от «Comparable [T] forSome {type T}» (начиная с версии 2.7 см. http://www.scala -lang.org / node / 43 )

См. Также «Экзистенциальные типы» в http://www.artima.com/scalazine/articles/scalas_type_system.html

2 голосов
/ 13 января 2011

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

implicit def orderingToOrdered [T] (x: T)(implicit ord: Ordering[T]) : Ordered[T]

Итак, пока есть Ordering[T],можно получить Ordered[T].Теперь, чтобы найти Ordering[T] внутри Ordering объекта:

implicit def ordered [A] (implicit arg0: (A) ⇒ Comparable[A]) : Ordering[A]

Итак, если вы передадите comparable: A with Comparable[A] чему-то ожидающему Ordered[A], он сделает это:

Ordered.orderingToOrdered(comparable)(Ordering.ordered(Predef.identity(comparable)))

Теперь, что касается вашего вопроса: использование экзистенциальных типов является правильным способом обработки необработанных типов Java.Теоретически это может привести к неправильному упорядочению, но на практике это крайне маловероятно.Однако у вас могут возникнуть проблемы с неявной неоднозначностью, поскольку в Scala уже есть неявное преобразование Comparable => Ordered, как показано выше.

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