2011-02-03 1 views
38

En essayant de trouver une solution à une autre question ([1]) je suis tombé sur une erreur d'expansion implicite divergente. Je cherche une explication sur ce que cela signifieQu'est-ce qu'une erreur d'expansion implicite divergente?

Voici le cas d'utilisation:

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 
               ^

Répondre

19

Si vous exécutez ce en scala avec l'argument -Xlog-implicits passé, vous obtenez plus d'informations:

scala.this.Prefed.conforms est pas une valeur implicite de validité (T) => Commandé [T] parce que:

incompatibilité de type:

trouvées: <: < [T, T]

requis: (T) => Commandé [T]

scala.this.predef.conforms est pas une valeur implicite de validité (Commandé [T]) => Ordonné [Ordonné [T]] parce que:

incompatibilité de type:

trouvé: <: < [Ordonné [T], Ordonné [T]]

nécessaire: (Ordonné [T]) => Commandé [Commandé [T]]

math.this.Ordering.ordered est pas une valeur implicite valable pour la commande [T] parce que:

arguments de type [T] ne sont pas conformes à la méthode des limites de paramètre de type commandé [A <: scala.math. Commandé [A]]

Ceci est principalement de la spéculation, mais semblerait avoir un sens. Je vais essayer d'étudier davantage:

Cela semble suggérer qu'il y a trois implicits qui sont considérés ici. En fin de compte, la signature de sorted l'oblige à trouver quelque chose de type Ordering[T]. Donc, il essaie de construire votre fonction implicite ordering. Tout d'abord, il essaie de remplir conv en trouvant un implicite de type (T) => Ordered[T], où il cherche dans Predef - qui semble aboyer dans le mauvais arbre. Il essaie alors de trouver un (Ordered[T]) => Ordered[Ordered[T]] implicite dans le même endroit, puisque by prend un paramètre implicite de type Ordering[S], où S est Ordered[T] en vertu de conv. Donc, il ne peut pas construire ordering.

Il essaie ensuite d'utiliser ordering dans math.Ordering, mais cela ne correspond pas non plus. Cependant, je pense que c'est ce qui donne le message quelque peu déroutant «implicits divergents». Le problème n'est pas qu'ils divergent, c'est qu'il n'y en a pas un qui soit approprié, mais il est troublé par le fait qu'il y a deux chemins à parcourir. Si l'on essaie de définir def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted sans la fonction ordonnée implicite, alors il échoue avec juste un gentil message disant qu'il ne peut pas trouver un implicite approprié.

+1

Je ne sais pas, je pensais que cela signifie qu'il y a récursivité. "Deux chemins à descendre" seraient des "implicites ambigus" de l'IIUC. – nafg

Questions connexes