scala - Confusing “diverging implicit expansion” error when using “sortBy”

一曲冷凌霜 提交于 2020-01-12 14:50:27

问题


I wonder why List(3,2,1).toIndexedSeq.sortBy(x=>x) doesn't work:

scala> List(3,2,1).toIndexedSeq.sortBy(x=>x) // Wrong
<console>:8: error: missing parameter type
              List(3,2,1).toIndexedSeq.sortBy(x=>x)
                                              ^
<console>:8: error: diverging implicit expansion for type scala.math.Ordering[B]
starting with method Tuple9 in object Ordering
              List(3,2,1).toIndexedSeq.sortBy(x=>x)
                                             ^

scala> Vector(3,2,1).sortBy(x=>x) // OK
res: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> Vector(3,2,1).asInstanceOf[IndexedSeq[Int]].sortBy(x=>x) // OK
res: IndexedSeq[Int] = Vector(1, 2, 3)

scala> List(3,2,1).toIndexedSeq.sortBy((x:Int)=>x) // OK
res: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3)

回答1:


If you look at the type signature of toIndexedSeq on List you'll see it takes a type parameter B, which can be any supertype of A:

def toIndexedSeq [B >: A] : IndexedSeq[B] 

If you leave out that type parameter then the compiler essentially has to guess what you meant, taking the most specific type possible. You could have meant List(3,2,1).toIndexedSeq[Any], which of course can't be sorted since there's no Ordering[Any]. It seems the compiler doesn't play "guess the type parameter" until the whole expression has been checked for correct typing (maybe someone who knows something about compiler internals can expand on this).

To make it work you can either a) provide the required type parameter yourself i.e.

List(3,2,1).toIndexedSeq[Int].sortBy(x=>x)

or b) separate the expression into two so that the type parameter has to be inferred before calling sortBy:

val lst = List(3,2,1).toIndexedSeq; lst.sortBy(x=>x)

Edit:

It's probably because sortBy takes a Function1 argument. The signature of sortBy is

def sortBy [B] (f: (A) => B)(implicit ord: Ordering[B]): IndexedSeq[A] 

whereas sorted (which you should use instead!) works fine with List(3,2,1).toIndexedSeq.sorted

def sorted [B >: A] (implicit ord: Ordering[B]): IndexedSeq[A] 

I'm not sure exactly why Function1 causes this problem and I'm going to bed so can't think about it further...



来源:https://stackoverflow.com/questions/9492904/scala-confusing-diverging-implicit-expansion-error-when-using-sortby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!