Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

scala - What is a diverging implicit expansion error?

While trying to find a solution to another question ([1]) I came across a diverging implicit expansion error. I'm looking for an explanation about what this means

Here's the use case:

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
                                                ^
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you run this in scala with the -Xlog-implicits argument passed, you get more information:

scala.this.Prefed.conforms is not a valid implicit value for (T) => Ordered[T] because:

type mismatch:

found : <:<[T,T]

required: (T) => Ordered[T]

scala.this.predef.conforms is not a valid implicit value for (Ordered[T]) => Ordered[Ordered[T]] because:

type mismatch:

found : <:<[Ordered[T], Ordered[T]]

required : (Ordered[T]) => Ordered[Ordered[T]]

math.this.Ordering.ordered is not a valid implicit value for Ordering[T] because:

type arguments [T] do not conform to method ordered's type parameter bounds [A <: scala.math.Ordered[A]]

This is mostly speculation, but would seem to make some sense. I will try to investigate further:

This seems to suggest that there are three implicits that are being considered here. Ultimately, the signature of sorted requires it to find something of type Ordering[T]. So it's trying to construct your implicit function ordering. Firstly, it's trying to fill in conv by finding an implicit of type (T) => Ordered[T], where it's searching in Predef - which seems like barking up the wrong tree. It's then trying to find an implicit for (Ordered[T]) => Ordered[Ordered[T]] in the same place, since by takes an implicit parameter of type Ordering[S], where S is Ordered[T] by virtue of conv. So it can't construct ordering.

It then tries to use ordering in math.Ordering, but this also doesn't fit. However, I think this is what's giving the somewhat confusing 'diverging implicits' message. The problem isn't that they're diverging, it's that there isn't a suitable one in scope, but it's being confused by the fact that there are two paths to go down. If one tries to define def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted without the implicit ordered function, then it fails with just a nice message saying that it can't find a suitable implicit.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...