Подтвердить что ты не робот

Параметры заказа и заказа и сравнения

Дано:

case class Person(name: String)

и попытаться сделать:

scala> List(Person("Tom"), Person("Bob")).sorted

приводит к жалобе о недостающем заказе.

<console>:8: error: could not find implicit value for parameter ord: Ordering[Person]
   List(Person("Tom"), Person("Bob")).sorted

Однако это:

case class Person(name: String) extends Ordered[Person] {
  def compare(that: Person) = this.name compare that.name }

работает нормально, как ожидалось:

scala> List(Person("Tom"), Person("Bob")).sorted
res12: List[Person] = List(Person(Bob), Person(Tom))

хотя там не задействованы Приказы или подразумеваемые.

Вопрос №1: что здесь происходит? (Мои деньги на что-то неявное...)

Однако, учитывая сказанное выше и тот факт, что это:

scala> Person("Tom") > Person("Bob")
res15: Boolean = true

работает, и это также:

scala> List(Some(2), None, Some(1)).sorted

работает из коробки:

res13: List[Option[Int]] = List(None, Some(1), Some(2))

Я бы ожидал, что это:

scala> Some(2) > Some(1)

также будет работать, однако это не так:

<console>:6: error: value > is not a member of Some[Int]
       Some(2) > Some(1)

Вопрос №2: почему бы и нет, и как я могу заставить его работать?

4b9b3361

Ответ 1

Относительно вашего первого вопроса: Ordered[T] extends Comparable[T]. Сопутствующий объект Ordering предоставляет неявный Ordering[T] для любого значения, которое может быть преобразовано в Comparable[T]:

implicit def ordered[A <% Comparable[A]]: Ordering[A]

Нет никакого неявного преобразования A : Ordering => Ordered[A] - поэтому Some(1) > Some(2) не будет работать.

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

Ответ 2

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

scala> import scala.math.Ordering.Implicits._
import scala.math.Ordering.Implicits._

scala> def cmpSome[T: Ordering](x: Option[T], y: Option[T]) = x < y
cmpSome: [T](x: Option[T], y: Option[T])(implicit evidence$1: Ordering[T])Boolean

Импорт дает вам неявное из Ordering для класса с операциями infix, так что достаточно иметь заказ без другого импорта.

Ответ 3

Определение метода List sorted:

def sorted [B >: A] (implicit ord: Ordering[B]): List[A]

Итак, да, неявные вещи происходят, но многие классы в стандартной библиотеке имеют неявные объекты, связанные с ними, без необходимости импортировать их в первую очередь.

Сопутствующий объект Ordering определяет кучу неявных порядков. Среди них опция OptionOrdering и IntOrdering, которая помогает объяснить возможность вызова списка sorted.

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

def cmpSome(l:Option[Int], r:Option[Int])(implicit ord:Ordering[Option[Int]]) = {
  import ord._
  l < r
}

scala> cmpSome(Some(0), Some(1))
res2: Boolean = true

Ответ 4

Чтобы ответить на второй вопрос, почему вы не можете сделать это: Some(2) > Some(1)

Вы можете импортировать и работать с Option[Int], а не Some[Int].

@ import scala.math.Ordering.Implicits._ 
import scala.math.Ordering.Implicits._
@ Some(2) > Some(1) // doesn't work
cmd11.sc:1: value > is not a member of Some[Int]
val res11 = Some(2) > Some(1)
                    ^
Compilation Failed
@ (Some(2): Option[Int]) > (Some(1): Option[Int]) // Option[Int] works fine
res11: Boolean = true
@ Option(2) > Option(1) 
res12: Boolean = true
@ (None: Option[Int]) > (Some(1): Option[Int]) 
res13: Boolean = false

На практике ваши типы, вероятно, будут Option[Int], а не Some[Int], поэтому он не будет таким уродливым, и вам не понадобится явное повышение.

Ответ 5

Я предполагаю, что вы понимаете, почему сортировка не работает, когда вы не проходите в Ordering, и ни один из них не доступен в области видимости. Что касается того, почему отсортированная функция работает, когда вы расширяете свой класс из Упорядоченного признака. Ответ заключается в том, что, когда вы расширяетесь от Упорядоченного признака, тип кода проверяет, содержит ли свойство функцию типа <, > и т.д. Поэтому нет необходимости делать неявное преобразование и, следовательно, не жалуется на недостающее неявное упорядочение.

Что касается вашего второго вопроса, Some(2) > Some(1) не будет работать, потому что Some не расшифровывает признак Ordered, также нет какой-либо неявной функции в области видимости, которая неявно преобразует Some в то, что имеет функцию >