什么是“发散隐式扩展"?scalac 消息是什么意思? [英] What's a "diverging implicit expansion" scalac message mean?

查看:37
本文介绍了什么是“发散隐式扩展"?scalac 消息是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个小示例程序,试图找出无法编译较大程序的原因.

I created a small example program to try to work out why a larger program wasn't compiling.

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

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

When I feed this to scala I get:

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"给出了以下内容:

Using "-explaintypes" offers nothing further. However, "-Xlog-implicits" gives the following:

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

但这对我没有帮助.想知道这条消息是什么意思以及如何解决?

but that's not helping me. Wondering what this message means and how to resolve it?

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

[Update] The same code today with Scala 2.11.0 produces a second error message in addition to the first about the "diverging implicit expansion". This second message is quite helpful.

$ 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

推荐答案

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

Shortly: your error message should simply be

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

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

The reason is simply that in Ordered[A], comparison are done with A, not with other orderings

def <(that: A): Boolean

那应该是 o1 <2,不是 o1 .(当然 1 < 2 也可以,但我希望你的代码只是其他东西的简化版本)

That should be o1 < 2, not o1 < o2. (of course 1 < 2 works too, but I expect your code is just a simplified version of something else)

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

However, before the compiler reports this simple error, if has to search whether some implicit in scope could fix the problem. It might convert the Ordering[Int] o2 to Int (cannot), or the Ordering[Int] o1 to something that has a def <(Ordered[Int]) method, for instance Ordered[Ordered[Int]]. And it happens that it must stop the search because it seems it could goes on indefinitely in kind of a cycle. The rule is given in the spec, p. 107 to 109 (spec for version 2.9). However, the rule for stopping the search is pessimistic, and it is possible that it drops a line of search that might have been successful, so the compiler feels it must report that. While in fact, most of the time as in here, the cycle was properly dropped, and no solution existed. This is what makes for a surprising error message. I think the simpler error should be reported too, and more prominently.

让我就隐式搜索中为什么可能存在循环给出一些有限的解释.可能有

Let me give some limited explanations on why there might be cycle in implicit search. There may be

implicit def f(implicit a: A): B

这意味着如果你有一个隐式的 A,你也有一个隐式的 B.这样就形成了一个类型之间的图:A 提供了 B.比这更复杂,它实际上是一个超图: implcit def f(implicit a: A, hidden b: B): C: A and B 提供 C.

which means that if you have an implicit A, you have an implicit B too. So that makes a graph between types: A provides B. It is more complex than that, it is actually an hypergraph: implcit def f(implicit a: A, implicit b: B): C: A and B provides C.

使用泛型,你有无限数量的类型和无限(超)图,通过子类型化变得更加复杂(如果你需要一个 AA 的任何子类型代码>就可以了.添加协方差/逆变隐含的子类型规则)

With generics, you have an infinite number of type and an infinite (hyper)graph, made still more complex by subtyping (if you need an A, any subtype of A will do. Add the subtyping rule implied by covariance/contravariance)

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

The graph may contain cycle: to get an A, you may just provide a B; to get a B, you may just provide a C; to get a C, you may just provide an A. That sums up to if you provide an A, you get an A, which is useless, and that line of search has to be dropped. This is not a problem in this case: it is an actual cycle, and there is no risk of bypassing a possible solution by dropping it.

但它可能更复杂.由于图是无限的,搜索可能是无限的而不完全循环.如果你有

But it may be more complex. As the graph is infinite, the search might be infinite without exactly cycling. If you have

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

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

then if you look for X[Int], you may look for X[X[Int]] instead, but then, with the same rule, you look for X[X[X[Int]]] and so on. It does not exactly cycle, yet the compiler does not pursue those lines and calls it diverging. Except that there may be an implicit X[X[X...X[Int]]]]] in implicit scope somewhere that would make it success. This is why the compiler reports that this line of exploration was dropped.

这篇关于什么是“发散隐式扩展"?scalac 消息是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆