O que é um erro de expansão implícita divergente?
Pergunta
Ao tentar encontrar uma solução para outra questão ( [1] ) Encontrei um erro de expansão implícita divergente.Estou procurando uma explicação sobre o que isso significa
Este é o 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
^
Solução
Se você executar isso em scala com o argumento -Xlog-implicits
passado, você obterá mais informações:
scala.this.Prefed.conforms não é um valor implícito válido para (T)=> Ordenado [T] porque:
incompatibilidade de tipo:
encontrado: <: <[T, T]
obrigatório: (T)=> Pedido [T]
scala.this.predef.conforms não é um valor implícito válido para (Ordered [T])=> Ordered [Ordered [T]] porque:
incompatibilidade de tipo:
encontrado: <: <[Ordenado [T], Ordenado [T]]
obrigatório: (Pedido [T])=> Pedido [Pedido [T]]
math.this.Ordering.ordered não é um valor implícito válido para Ordering [T] porque:
os argumentos de tipo [T] não estão em conformidade com os limites dos parâmetros de tipo do método encomendado [A <: scala.math.Ordered [A]]
Isso é principalmente especulação, mas parece fazer algum sentido. Vou tentar investigar mais a fundo:
Isso parece sugerir que há três implícitos que estão sendo considerados aqui. Em última análise, a assinatura de sorted
exige que ele encontre algo do tipo Ordering[T]
. Portanto, ele está tentando construir sua função ordering
implícita. Em primeiro lugar, ele está tentando preencher conv
encontrando um código implícito do tipo (T) => Ordered[T]
, onde está pesquisando em Predef - o que parece estar latindo na árvore errada. Em seguida, ele está tentando encontrar um código implícito para (Ordered[T]) => Ordered[Ordered[T]]
no mesmo lugar, já que by
usa um parâmetro implícito do tipo Ordering[S]
, onde S
é Ordered[T]
em virtude de conv
. Portanto, ele não pode construir ordering
.
Em seguida, ele tenta usar ordering
em math.Ordering, mas também não serve. No entanto, acho que é isso que está dando a mensagem um tanto confusa de 'implícitos divergentes'. O problema não é que estejam divergindo, é que não há um adequado no escopo, mas está sendo confundido pelo fato de que há dois caminhos a percorrer. Se alguém tentar definir def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
sem a função ordenada implícita, ele falhará apenas com uma boa mensagem dizendo que não foi possível encontrar um implícito adequado.