Почему иногда имеет значение порядок неявных параметров? - PullRequest
1 голос
/ 02 августа 2020

Что касается следующего фрагмента кода (scala 2.12.10), мой вопрос: почему порядок имеет значение в этом c случае для неявных аргументов. Я также не понимаю, почему компилятор сообщает мне, что существуют неоднозначные неявные значения, я вижу какие-либо намеки на это.

import scala.reflect.ClassTag

trait Wrapper[T] {

  implicit def ct: ClassTag[T]

  // First try using scala syntaxic sugar for single type parameter type class
  def asPair1[K : ClassTag, V : ClassTag](implicit ev: T <:< (K, V)): Unit = Unit
  
  // Same as asPair1 with explicit implicits ClassTag, in same order than with syntaxic sugar version
  def asPair1Bis[K, V](implicit kt: ClassTag[K], vt: ClassTag[V], ev: T <:< (K, V)): Unit = Unit

  // Workaround
  def asPair2[K, V](implicit ev: T <:< (K, V), kt: ClassTag[K], vt: ClassTag[V]): Unit = Unit
  
}

trait Test[K, V] {
  
  implicit def kt: ClassTag[K]
  implicit def vt: ClassTag[V]
  
  val w: Wrapper[(K, V)]
  
  w.asPair1  // Fails
/**
error: ambiguous implicit values:
 both method kt in trait Test of type => reflect.this.ClassTag[K]
 and method vt in trait Test of type => reflect.this.ClassTag[V]
 match expected type reflect.this.ClassTag[K]
    w.asPair1  // Fails
      ^
error: No ClassTag available for K
    w.asPair1  // Fails
      ^
error: not enough arguments for method asPair1: (implicit   evidence$1: reflect.this.ClassTag[K], implicit   evidence$2: reflect.this.ClassTag[V], implicit  ev: $less$colon$less[scala.this.Tuple2[K,V],scala.this.Tuple2[K,V]])scala.this.Unit.
Unspecified value parameters evidence$1, evidence$2, ev.
    w.asPair1  // Fails
*/

  w.asPair1Bis // Fails
  w.asPair2  // Works


  val w2: Wrapper[(Int, Double)]
  w2.asPair1 // Fails with exact same logs than with `w`
  w2.asPair2


}

1 Ответ

2 голосов
/ 02 августа 2020

Итак, во-первых, не смешивайте границы контекста и имплициты, это считается плохой практикой; см. this для получения дополнительной информации.

Во-вторых, порядок имеет значение, потому что, если ev идет первым, то параметры типа K и V решаются компилятором до того, как он попытается для поиска в их ClassTags . В другом случае компилятор не имеет информации о том, что такое K и V, поэтому он будет пытаться просто предположить все, что может найти, таким образом находя два возможных неявных ClassTags (как для внешнего K, так и для внешнего V) создаёт двусмысленность.

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