Подтвердить что ты не робот

Что означает "скачкообразное сообщение с расплывчатым расширением"?

Я создал небольшую примерную программу, чтобы попытаться решить, почему большая программа не компилируется.

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
4b9b3361

Ответ 1

Вкратце: ваша ошибка messaage должна быть просто   ошибка: тип несоответствия   найдено: Заказ [Int]   требуется: 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]]. И бывает, что он должен остановить поиск, потому что кажется, что он может продолжаться бесконечно в виде цикла. Правило дано в spec, 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. сделает правило подтипирования, подразумеваемое ковариацией/контравариантностью )

График может содержать цикл: для получения 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]]]]] в неявной области где-то, что сделало бы его успешным. Вот почему компилятор сообщает, что эта линия исследования была удалена.