¿Qué es un error de expansión implícito divergente?
Pregunta
Mientras intentaba encontrar una solución a otra pregunta ([1]) Me encontré con un error de expansión implícito divergente.Estoy buscando una explicación sobre lo que esto significa.
Este es el caso de uso:
scala> implicit def ordering[T](implicit conv: T => Ordered[T], res: Ordering[Ordered[T]]) = Ordering.by(conv)
ordering: [T](implicit conv: (T) => Ordered[T],implicit res: Ordering[Ordered[T]])scala.math.Ordering[T]
scala> def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
<console>:6: error: diverging implicit expansion for type Ordering[T]
starting with method ordering in object $iw
def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
^
Solución
Si ejecuta esto en Scala con el -Xlog-implicits
argumento pasado, obtienes más información:
scala.this.Prefed.conforms no es un valor implícito válido para (T) => Ordered[T] porque:
el tipo no coincide:
encontró :<:<[T,T]
requerido:(T) => Ordenado[T]
scala.this.predef.conforms no es un valor implícito válido para (Ordered[T]) => Ordered[Ordered[T]] porque:
el tipo no coincide:
encontró :<:<[Ordenado[T], Ordenado[T]]
requerido :(Ordenado[T]) => Ordenado[Ordenado[T]]
math.this.Ordering.ordered no es un valor implícito válido para Ordering[T] porque:
Los argumentos de tipo [T] no se ajustan a los límites de los parámetros de tipo del método ordenado [A <:scala.math.Ordenado[A]]
Esto es principalmente especulación, pero parece tener cierto sentido.Intentaré investigar más a fondo:
Esto parece sugerir que hay tres implicaciones que se están considerando aquí.En definitiva, la firma de sorted
requiere que encuentre algo de tipo Ordering[T]
.Entonces está tratando de construir su función implícita. ordering
.En primer lugar, está intentando completar conv
al encontrar un tipo implícito (T) => Ordered[T]
, donde está buscando en Predef, lo que parece como ladrarle al árbol equivocado.Luego está tratando de encontrar un implícito para (Ordered[T]) => Ordered[Ordered[T]]
en el mismo lugar, ya que by
toma un parámetro implícito de tipo Ordering[S]
, dónde S
es Ordered[T]
en virtud de conv
.Entonces no puede construir ordering
.
Luego intenta usar ordering
en matemáticas. Ordenar, pero esto tampoco encaja.Sin embargo, creo que esto es lo que transmite el mensaje algo confuso de "implícitos divergentes".El problema no es que estén divergiendo, es que no hay uno adecuado en su alcance, sino que hay confusión por el hecho de que hay dos caminos a seguir.Si uno intenta definir def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
sin la función ordenada implícita, falla con solo un bonito mensaje que dice que no puede encontrar una función implícita adecuada.