【问题标题】:What's a "diverging implicit expansion" scalac message mean?什么是“发散隐式扩展”scalac消息是什么意思?
【发布时间】:2018-03-15 22:08:54
【问题描述】:

我创建了一个小示例程序来尝试找出较大的程序无法编译的原因。

val o1: Ordered[Int] = 1
val o2: Ordered[Int] = 2
println(o1 < o2)

当我将它提供给 scala 时,我得到:

Ordered.scala:3: error: diverging implicit expansion for type scala.math.Ordering[Ordered[Int]]
starting with method ordered in trait LowPriorityOrderingImplicits
println(o1 < o2)
        ^
one error found

使用“-explaintypes”没有进一步的作用。但是,“-Xlog-implicits”给出以下内容:

math.this.Ordering.comparatorToOrdering is not a valid implicit value for scala.math.Ordering[Ordered[Int]] because:
could not find implicit value for parameter cmp: java.util.Comparator[Ordered[Int]]
scala.this.Predef.conforms is not a valid implicit value for Ordered[Int] => java.lang.Comparable[Ordered[Int]] because:
type mismatch;
 found   : <:<[Ordered[Int],Ordered[Int]]
 required: Ordered[Int] => java.lang.Comparable[Ordered[Int]]
/Users/steshaw/Projects/playground/scala/programming-in-scala/Ordered.scala:3: error: diverging implicit expansion for type scala.math.Ordering[Ordered[Int]]
starting with method ordered in trait LowPriorityOrderingImplicits
println(o1 < o2)
        ^
math.this.Ordering.comparatorToOrdering is not a valid implicit value for scala.math.Ordering[Ordered[Int]] because:
could not find implicit value for parameter cmp: java.util.Comparator[Ordered[Int]]
scala.this.Predef.conforms is not a valid implicit value for Ordered[Int] => java.lang.Comparable[Ordered[Int]] because:
type mismatch;
 found   : <:<[Ordered[Int],Ordered[Int]]
 required: Ordered[Int] => java.lang.Comparable[Ordered[Int]]
one error found

但这对我没有帮助。想知道此消息的含义以及如何解决?

[更新] 今天与 Scala 2.11.0 相同的代码除了第一个关于“发散隐式扩展”的错误消息外,还会产生第二个错误消息。第二条消息很有帮助。

$ scala Ordered.scala
Ordered.scala:3: error: diverging implicit expansion for type scala.math.Ordering[Ordered[Int]]
starting with method comparatorToOrdering in trait LowPriorityOrderingImplicits
println(o1 < o2)
        ^
/Users/steshaw/Projects/playground/scala/scalac-errors/Ordered.scala:3: error: type mismatch;
 found   : Ordered[Int]
 required: Int
println(o1 < o2)
             ^
two errors found

【问题讨论】:

    标签: scala


    【解决方案1】:

    简而言之:您的错误信息应该是

    error: type mismatch 
    found: Ordering[Int]
    required: Int.
    

    原因很简单,在Ordered[A]中,比较是与A进行的,而不是与其他排序

    def <(that: A): Boolean
    

    应该是o1 &lt; 2,而不是o1 &lt; o2。 (当然1 &lt; 2 也可以,但我希望你的代码只是其他东西的简化版本)

    但是,在编译器报告这个简单的错误之前,if 必须搜索一些隐式范围是否可以解决问题。它可能会将Ordering[Int] o2 转换为Int(不能),或者将Ordering[Int] o1 转换为具有def &lt;(Ordered[Int]) 方法的东西,例如Ordered[Ordered[Int]]。碰巧它必须停止搜索,因为它似乎可以无限期地循环下去。该规则在规范中给出,p。 107 到 109(2.9 版规范)。但是,停止搜索的规则是悲观的,它可能会丢弃可能成功的搜索行,因此编译器认为它必须报告这一点。而事实上,大多数时候,就像这里一样,循环被适当地丢弃了,并且不存在解决方案。这就是导致令人惊讶的错误消息的原因。我认为更简单的错误也应该报告,而且更突出。

    让我对为什么隐式搜索可能存在循环进行一些有限的解释。可能有

    implicit def f(implicit a: A): B
    

    这意味着如果你有一个隐含的A,你也有一个隐含的B。这样就可以在类型之间制作图表:A 提供 B。它比这更复杂,它实际上是一个超图:implcit def f(implicit a: A, implicit b: B): C:AB 提供C

    使用泛型,您有无限数量的类型和无限(超)图,通过子类型化变得更加复杂(如果您需要 AA 的任何子类型都可以。添加隐含的子类型化规则通过协方差/逆变)

    图表可能包含循环:要获得A,您只需提供B;要获得B,您只需提供C;要获得C,您只需提供A。总而言之,如果您提供A,您将获得A,这是无用的,并且必须删除该搜索行。在这种情况下,这不是问题:它是一个实际的循环,并且不存在通过丢弃它来绕过可能的解决方案的风险。

    但它可能更复杂。由于图形是无限的,因此搜索可能是无限的,而没有完全循环。如果你有

    implicit def[A](x: X[X[A]]): X[A] 
    

    然后,如果您查找X[Int],您可能会查找X[X[Int]],但是按照相同的规则,您查找X[X[X[Int]]] 等等。它并不完全循环,但编译器并不追求这些行并将其称为发散。除了在隐式范围内可能有一个隐式X[X[X...X[Int]]]]] 可以使它成功。这就是为什么编译器报告这条探索路线被放弃了。

    【讨论】:

      猜你喜欢
      • 2011-06-20
      • 2017-06-29
      • 2012-01-20
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 2022-07-22
      • 1970-01-01
      相关资源
      最近更新 更多