Почему этот призыв к безоговорочно неоднозначен?
Подпись sum
метод на TraversableOnce
как следует:
def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
Я могу использовать это таким образом:
scala> (1 to 10).sum
res0: Int = 55
В этом случае компилятор вводит Numeric[B]
само по себе, поэтому в области видимости должно быть однозначное неявное значение этого типа. Если я использую Predef.implicitly
чтобы сделать это самостоятельно, это происходит:
scala> (1 to 10).sum(implicitly)
<console>:6: error: ambiguous implicit values:
both method conforms in object Predef of type [A]<:<[A,A]
and method stringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String]
match expected type T
(1 to 10).sum(implicitly)
^
Почему это неоднозначно?
Я могу заставить двусмысленность исчезнуть либо
scala> (1 to 10).sum(implicitly[Numeric[Int]])
res2: Int = 55
Или же
scala> (1 to 10).sum[Int](implicitly)
res3: Int = 55
Я предполагаю, что это как-то связано с тем, что sum объявляет новый тип параметра B >: A
(ясно, см. ниже), но я все еще не понимаю, почему что-то однозначно можно найти в первом примере, а не во втором?
РЕДАКТИРОВАТЬ - для устранения бессмысленного комментария subub (ниже)
scala> class As[A](as : A*) {
| def sum(implicit num : Numeric[A]) : A = as.foldLeft(num.zero)(num.plus)
| }
defined class As
scala> (new As(1, 2, 3, 4)).sum
res0: Int = 10
scala> (new As(1, 2, 3, 4)).sum(implicitly)
res1: Int = 10
Таким образом, вы можете видеть, что это не тот случай, когда любой призыв к неявно является неоднозначным
1 ответ
Краткий ответ: из-за B >: A
результирующий тип для implicitly
Вызов не может быть выведен.
Более длинный ответ. Когда аргумент определен как implicit
отсутствует, компилятор будет искать в текущей области любое неявное значение типа Numeric[B >: Int]
и будем использовать самые конкретные - Numeric[Int]
,
Но если вы укажете аргумент как implicitly
(звонок в implicitly [T] (implicit e: T) : T
) сначала аргумент типа T
должен быть решен. И Scala Runtime явно не в состоянии сделать это.
Это то же самое, что назвать это:
scala> var f = implicitly
<console>:5: error: ambiguous implicit values:
both method conforms in object Predef of type [A]<:<[A,A]
and method stringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String]
match expected type T
var f = implicitly
^