为什么这个调用隐含地不明确?

发布于 2024-10-30 20:13:51 字数 1512 浏览 3 评论 0原文

TraversableOnce 上的 sum 方法的签名如下:

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 有关(很明显,请参见下面的编辑),但我仍然很困惑为什么在第一个例子中可以明确地找到某些东西,但在第二个例子中却不能?

编辑 - 解决 subsub 的愚蠢评论(如下)

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

因此,您可以看到任何隐式调用都不是不明确的

The signature of the sum method on TraversableOnce is as follows:

def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)

I can use it thus:

scala> (1 to 10).sum
res0: Int = 55

In this case, the compiler is injecting the Numeric[B] itself, so there must be an unambiguous implicit value of this type in scope. If I use Predef.implicitly to inject it myself, this happens:

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)
                 ^

Why is this ambiguous?

I can make the ambiguity disappear either by

scala> (1 to 10).sum(implicitly[Numeric[Int]])
res2: Int = 55

Or

scala> (1 to 10).sum[Int](implicitly)
res3: Int = 55

I presume that this has something to do with the fact that sum declares a new type parameter B >: A (it clearly is, see below edit), but I'm still confused about why something can be unambiguously found in the first example but not the second?

EDIT - to address subsub's inane comment (below)

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

So, you can see that it is not the case that any call to implicitly is ambiguous

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不咬妳我踢妳 2024-11-06 20:13:51

简短回答:因为B >:无法推断隐式调用的A结果类型。

更长的答案。当定义为 implicit 的参数丢失时,编译器将在当前范围中搜索 Numeric[B >: Int] 类型的任何隐式值,并使用最具体的 - 数字[Int]

但是,如果您将参数指定为implicitly(调用implicitly [T] (implicit e: T) : T),首先是类型参数T > 必须解决。而 scala 运行时显然无法做到这一点。

这与调用它是一样的:

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
               ^

Short answer: Because of B >: A resulting type for implicitly call can not be inferred.

Longer answer. When argument defined as implicit is missing, compiler will search current scope for any implicit value of type Numeric[B >: Int] and will use the most specific - Numeric[Int].

But if you specify argument as implicitly (a call to the implicitly [T] (implicit e: T) : T) first the type argument T must be resolved. And scala runtime clearly fails to do so.

It is the same as calling this:

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
               ^
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文