I’m trying to write a function that maps a sequence S by a function F (I’ll call it F(S)), zips the resulting values (F(S)) with S, and sorts the result by F(S), returning the sorted zipped values (I hope the code clears this up, it’s difficult to put into text)
Here’s my current code:
def sortByAndReturnZippedMetric[S,M<:Ordering[AnyVal]]( s:Seq[S], mapper:S=>M):Seq[(M,S)] =
s.map(mapper).zip(s).sortBy(_._1)
Scalac is complaining, though:
error: diverging implicit expansion for type scala.math.Ordering[M]
starting with method comparatorToOrdering in trait LowPriorityOrderingImplicits
s.map(mapper).zip(s).sortBy(_._1)
^
I’d appreciate some pointers as to what might be wrong…
Orderingis a type class, which means that if you want to capture the fact thatAis ordered in a particular way, you simply put an implicit instance ofOrdering[A]into scope—you don’t haveAextendOrdering[A](orOrdering[AnyVal], etc.).The advantage of this approach is that you can work with multiple orderings for a particular type (although only one implicit ordering can be in scope at a time for a type). So for example I can write the following:
Here the implicit ordering for integers (
Ordering.Int) is used as the implicit argument tosorted, but we could also explicitly pass a differentOrdering. For example, we could create a new ordering by reversing the implicit one:In your case
sortByis looking for anOrdering[Ordering[AnyVal]], which doesn’t exist. You can easily fix this by using a context bound to indicate that you need an ordering forM, instead of havingMextendOrdering[AnyVal]:Or you can skip the syntactic sugar and use an implicit argument:
This is exactly equivalent to the version with the context bound.