Когда неявный объект импортируется из объекта-компаньона?

Я знаю, что это уже сотый вопрос о имплицитах / сопутствующих объектах. Однако я нигде не нашел этот случай.

В "Tryout", почему A не требуется импорт для неявного класса, а B это нужно? Thankx.

class LongConsumer {
  def consume(l: Long) = Unit
}

case class X(x: Long)

object X extends (Long => X) {
  implicit class ConsumeX(val c: LongConsumer) extends AnyVal {
    def consume(x: X) = c consume x.x
  }
  implicit class EatX(val c: LongConsumer) extends AnyVal {
    def eat(x: X) = c consume x.x
  }
}

object Tryout {
  // A: does not need import to compile - why?
  new LongConsumer().consume(X(10L))

  // B: needs import to compile - why?
  import X.EatX
  new LongConsumer().eat(X(10L))
}

1 ответ

Решение

Есть только три случая для просмотра.

http://www.scala-lang.org/files/archive/spec/2.11/07-implicit-parameters-and-views.html

Ваш случай A является № 1, где X не является длинным, как ожидается от потребления. (Изменить: Извините, я смотрю Hulu. Это № 3, где потребление не применяется. Конвертация из LongConsumer в ConsumeX. В этом случае я бы не ожидал, что неявная область действия X будет в игре.)

Но обратите внимание, что неявная область действия - это область действия X => Long.

Область действия Function[X, Long] включает область действия обоих параметров типа, а область действия X включает сопутствующий элемент X. (В предыдущем разделе 7.2 перечислено, что находится в неявной области действия.) Интуиция заключается в том, что у вас есть один тип в руке, но нужен другой; любой тип может обеспечить преобразование.

В вашем случае B это дело № 2, а объем LongConsumer не обеспечивает преобразование.

Я попросил ОД для разъяснения. -Ytyper-debug говорит, что это вторая попытка.

|    |    second try: (l: Long)Unit.type and eatery.X.type
|    |    |-- eatery.X.type EXPRmode (silent: value <local Tryout> in Tryout)
|    |    |    |-- X.apply BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value <local Tryout> in Tryout)
|    |    |    |    \-> (x: Long)eatery.X
|    |    |    \-> eatery.X
|    |    |-- eatery.this.X.ConsumeX BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value <local Tryout> in Tryout) implicits disabled
|    |    |    \-> eatery.X.ConsumeX.type <and> (c: eatery.LongConsumer)eatery.X.ConsumeX
|    |    |-- (c: eatery.LongConsumer)eatery.X.ConsumeX EXPRmode-POLYmode-QUALmode (site: value <local Tryout> in Tryout)
|    |    |    \-> eatery.X.ConsumeX
|    |    |-- eatery.this.X.ConsumeX(new LongConsumer()).consume BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value <local Tryout> in Tryout)
|    |    |    \-> (x: eatery.X)Unit.type (with underlying type (x: eatery.X)Unit.type)
|    |    \-> Unit.type
|    \-> [object Tryout] eatery.Tryout.type

Результаты в:

https://issues.scala-lang.org/browse/SI-5089

@retronym говорит: более широкий вопрос о том, почему неявная область действия включает компаньонов типов аргументов приложений, известен как "проблема 1 + BigInteger(1)"

Видно, когда вы так говорите.

Также см. Здесь описание ссылки в разделе "Неявная область действия типа аргумента".

Другие вопросы по тегам