#scala #implicit
#scala #неявный
Вопрос:
Я немного поиграл с неявным разрешением и хотел понять, для чего полезен этот неявный val? При упорядочении мы имеем
trait OptionOrdering[T] extends Ordering[Option[T]] {
def optionOrdering: Ordering[T]
def compare(x: Option[T], y: Option[T]) = (x, y) match {
case (None, None) => 0
case (None, _) => -1
case (_, None) => 1
case (Some(x), Some(y)) => optionOrdering.compare(x, y)
}
}
implicit def Option[T](implicit ord: Ordering[T]): Ordering[Option[T]] =
new OptionOrdering[T] { val optionOrdering = ord }
Интересно, когда неявный параметр def[T] (неявный порядок: упорядочивание [T]): Упорядочивание[Option [T]] полезно или вызывается.
Я попробовал следующее:
def test[Option[T]: Ordering](value1: Option[T], value2: Option[T]) = {
val e = implicitly(Ordering[Option[T]]).compare(value1, value2)
}
Но компилятору это не нравится.
не найдено: type T def test[Опция [T]: Упорядочивание](значение 1: опция [T], значение 2: опция [T]) = {
и если я сделаю, что предоставлено, может не иметь смысла, но только ради
def test[Option[Int]: Ordering](value1: Option[Int], value2: Option[Int]) = {
val e = implicitly(Ordering[Option[Int]]).compare(value1, value2)
}
I get
type Option takes type parameters
def test[Option[Int]: Ordering](value1: Option[Int], value2: Option[Int]) = {
No implicit Ordering defined for Option[Int]
Может кто-нибудь привести пример того, как использовать этот неявный и / или где он полезен и действительно используется?
Я предполагаю, что когда возникает необходимость в упорядочении [Option [T]], тогда эта функция вызывается для разрешения неявного. Но я не могу этого сделать….
РЕДАКТИРОВАТЬ Ну, я написал следующее, что имеет больше смысла
def test(value1: Option[Int], value2: Option[Int]) = {
val e = implicitly(Ordering[Option[Int]]).compare(value1, value2)
}
Тогда я не понимаю, связана ли проблема с контекстом с
def test[Option[T]: Ordering](value1: Option[T], value2: Option[T]) = {
val e = implicitly(Ordering[Option[T]]).compare(value1, value2)
}
What's wrong with writing a context bound like that ?
Комментарии:
1. Обратите внимание, что довольно странно иметь эту особенность, обычно вы просто реализуете анонимный класс в теле
implicit def
Ответ №1:
Интересно, когда неявный параметр def[T] (неявный порядок: упорядочивание [T]): Упорядочивание[Option [T]] полезно или вызывается.
Неявные методы могут использоваться для создания экземпляров класса типа из других экземпляров класса типа, которые могут сохранять шаблон
implicit def Option[T](implicit ord: Ordering[T]): Ordering[Option[T]] =
new OptionOrdering[T] { val optionOrdering = ord }
Например, для данного экземпляра класса типа Ordering[Int]
вышеупомянутый неявный метод может создавать экземпляр класса типа Ordering[Option[Int]]
. (Не забудьте implicit
параметр, иначе мы получим неявное преобразование, которое не одобряется).
что не так с [Option [T]: Упорядочивание]
Ключ в том, чтобы понять разницу между конструктором типа и правильным типом. Например, Option
есть конструктор типов, который может создавать правильный тип Option[Int]
. Предложение параметра типа [Option[T]: Ordering]
в вашем определении
def test[Option[T]: Ordering](value1: Option[T], value2: Option[T])
на самом деле не указывает Option
конструктор типа. Просто так получилось, что вы назвали его так же, однако то, что вы указали, на самом деле больше похоже
def test[F[T]: Ordering](value1: F[T], value2: F[T])
Кроме того, T
in F[T]
фактически не может использоваться в списке параметров метода, поэтому на самом деле ваше определение больше похоже на so
def test[F[_]: Ordering](value1: F[T], value2: F[T])
Теперь ошибки должны быть понятнее; F[_]: Ordering
требуется экземпляр класса типа, Ordering[F]
где F
является конструктором типа, однако таких экземпляров класса типа нет, потому что определение класса типа Ordering
является
trait Ordering[T]
где T
— правильный тип. В противном случае это было бы определено примерно так
trait Ordering[F[_]]
Примером такого класса типа является Functor
trait Functor[F[_]]
Следовательно, чтобы синтаксически исправить ваше определение, попробуйте что-то вроде
def test[T](value1: Option[T], value2: Option[T])(implicit ev: Ordering[Option[T]]) = {
ev.compare(value1, value2)
}
test(Some(1), Some(42))
// res0: Int = -1
implicitly[Ordering[Option[Int]]].compare(Some(1), Some(42))
// res1: Int = -1
Здесь test(Some(1), Some(42))
эквивалентно
test[Int](Some(1), Some(42))(Option[Int])
|
implicit method call
Комментарии:
1. Да, я согласен с ошибкой, я оставил ее для истории. Я получаю неявный, который вызывает неявный параметр. С этим проблем нет. Неявным разрешением может быть значение val или def, которые имеют только неявные параметры и возвращают нужный нам тип. Это нормально, однако, почему я не могу использовать контекстную привязку вместо явно неявного параметра, который вы сделали?
2. Я думаю, вопрос скорее в синтаксисе, связанном с контекстом, что не так с
[Option[T]: Ordering]
почему его нельзя перевести наimplicit ev: Ordering[Option[T]]
?