2011-10-31 30 views
12

我創建了一個小例子程序,試圖找出爲什麼一個較大的程序沒有編譯。什麼是「分散隱式擴展」scalac消息是什麼意思?

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

當我喂這斯卡拉我得到:

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相同的代碼除了第一個關於「diverging implicit expansion」外,還產生了第二個錯誤信息。第二條消息非常有用。

$ 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 

回答

25

不久:你的錯誤messaage應該簡單地 錯誤:發現類型不匹配 :訂購所需[INT] :詮釋。

原因很簡單,在Ordered[A],比較與A進行,而不是與其他排序

def <(that: A): Boolean 

這應該是o1 < 2,不o1 < o2。 (當然1 < 2也可以,但我希望你的代碼只是其他東西的簡化版本)

但是,在編譯器報告這個簡單的錯誤之前,如果必須搜索一些隱含的範圍能否解決問題。它可能會將Ordering[Int]o2轉換爲Int(不可)或Ordering[Int]o1轉換爲具有def <(Ordered[Int])方法的東西,例如Ordered[Ordered[Int]]。而且恰巧它必須停止搜索,因爲它似乎可能無限期地在某種循環中繼續。該規則在規範中給出,p。 107至109(規範版本2.9)。但是,停止搜索的規則是悲觀的,它可能會刪除可能已經成功的搜索行,因此編譯器認爲它必須報告。事實上,大部分時間都在這裏,週期適當下降,並沒有解決方案。這是一個令人驚訝的錯誤信息。我認爲更簡單的錯誤也應該被報告,並且更加突出。

讓我給出一些有限的解釋,說明爲什麼在隱式搜索中可能存在循環。有可能是

implicit def f(implicit a: A): B 

這意味着如果你有一個隱式的A,你也有一個隱含的B.因此,在類型之間形成一個圖:A提供B.它比這更復雜,它實際上是一個超圖:'implcit def f(隱式a:A,隱式b:B):C':A和B提供C.使用泛型,你有無限數量的類型和無限(超)圖形,通過子類型變得更加複雜(如果你需要一個A,A的任何子類型都會做)。添加協方差隱含的子類型規則/逆轉)

該圖可能包含cycle:獲得一個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]]]等。它並不完全循環,但編譯器並不追求這些線路並稱之爲分歧。除此之外,隱式作用域中可能存在一個隱含的暗示範圍,可能會使其成功。這就是爲什麼編譯器報告說這一行的探索被放棄了。