【问题标题】:Why is this call to implicitly ambiguous?为什么这个调用隐含模棱两可?
【发布时间】:2023-03-24 23:37:01
【问题描述】:

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 &gt;: 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

所以,你可以看到,任何隐式调用都不是模棱两可的

【问题讨论】:

  • 它与任何隐式调用一样模棱两可。 scala&gt; Predef.implicitly &lt;console&gt;:6: error: ambiguous implicit values: both method conforms in object Predef of type [A]&lt;:&lt;[A,A] and method stringCanBuildFrom in object Predef of type =&gt; scala.collection.generic.CanBuildFrom[String,Char,String] match expected type T Predef.implicitly。因此,潜在的含义可能类似于“在这里找不到任何合适的隐含事物,请帮助!”
  • @subsub - 查看我的编辑。这正是正在发生的事情。我在问为什么隐式调用被推断为导致模棱两可的隐式。如果cope中有匹配的隐式值,为什么无参数调用有类似的问题?
  • 如果我的评论很空洞,你为什么要编辑你的问题?好吧,这是另一个:class Bs[A](bs : TraversableOnce[A]) { def sum(implicit num : Numeric[A]) : A = bs.foldLeft(num.zero)(num.plus) }; (new Bs(1 to 10)).sum(implicitly)
  • 向你证明这是多么愚蠢。我问为什么在特定情况中对implicitly 的调用是模棱两可的。你回答:“嗯,这里很模糊”对于一个完全不同的情况
  • 有趣的是,接受的答案包括那种完全不同的空洞情况;-)

标签: scala implicit


【解决方案1】:

简答:由于B &gt;: A 导致implicitly 调用的类型无法推断。

更长的答案。当缺少定义为implicit 的参数时,编译器将在当前范围内搜索Numeric[B &gt;: Int] 类型的任何隐式值,并将使用最具体的-Numeric[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
               ^

【讨论】:

    猜你喜欢
    • 2011-08-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    相关资源
    最近更新 更多