You have chosen a tough nut to crack as a beginner before Scala! :-)
Well, a short tour, don't expect to fully understand this now. First, note that the problem occurs with the ++ method. Searching for its definition, we find it based on MapLike , getting either Iterator or Traversable . Since y is a SortedMap , the version of Traversable .
Pay attention to your extensive type signature that is passed to CanBuildFrom . This is passed implicitly, so you usually don't need to worry about it. However, to understand what is happening, this time you do.
You can find CanBuildFrom by clicking on it where it appears in the ++ definition, or by filtering. As Randall mentioned in the comments, there is an unmarked blank box in the upper left corner of the skydock page. You just need to click there and enter, and it will return matches for what you typed.
So, find the CanBuildFrom on the ScalaDoc and select it. It has a large number of subclasses, each of which is responsible for creating a certain type of collection. Locate and click on the subclass of SortedMapCanBuildFrom . This is the class of the object that you want to create the SortedMap from Traversable . Notice the instance constructor (constructor for the class) that receives the implicit Ordering parameter. Now we are getting closer.
This time use the filter filter to search for Ordering . Its companion object (click on the small “o” name) contains the implicit that Ordering s will generate, since companion objects will be examined for implications that generate instances or transformations for this class. It is defined inside the LowPriorityOrderingImplicits attribute, the Ordering object expands, and looking at it, you will see the ordered[A <: Ordered[A]] method that will generate the required Ordering ... or create it, unless there was a problem.
It can be assumed that an implicit conversion from X to Ordered[X] would be sufficient, as before, before exploring this more thoroughly. This, however, is a conversion of objects, and ordered expects to get a type that is a subtype of Ordered[X] . Although you can convert an object of type X to an object of type Ordered[X] , X , by itself, is not a subtype of Ordered[X] , so it cannot be passed as an argument to ordered .
Alternatively, you can create an implicit val Ordering[X] instead of def Ordered[X] and you will run into a problem. In particular:
object ViewBoundExample { class X def combine[Y](a: SortedMap[X, Y], b: SortedMap[X, Y]): SortedMap[X, Y] = { a ++ b } implicit val orderingX = new Ordering[X] { def compare(x: X, y: X) = 0 } }
I think that most people who start a reaction to ordered / Ordering should be perplexed: why are classes for the same thing? The first applies to java.lang.Comparable , and the second to java.util.Comparator . Alas, the type signature for compare pretty much sums up the main difference:
def compare(that: A): Int // Ordered def compare(x: T, y: T): Int // Ordering
Using Ordered[A] requires either A extend Ordered[A] , which requires it to modify the definition of A or to pass a method that can convert A to Ordered[A] . Scala is very good at making the latter easy, but then you need to convert each instance before comparing.
On the other hand, using Ordering[A] requires the creation of a single object, such as the one shown above. When you use it, you simply pass two objects of type A - compare - no objects are created in the process.
Thus, there are some performance benefits, but there is a much more important reason for Scala to prefer Ordering over ordered . Look again at the companion object on Ordering . You will notice that for many of the Scala classes defined in it, there are several implications. You may recall that you mentioned earlier that an implicit class T will be searched for an object T , and what exactly is happening.
This can be done for ordered . However, this is the anchor point, this means that every method that supports both Ordering and ordered will not work! This is because Scala will look for implicit to make it work, and will find two: one for Ordering , one for ordered . Unable to decide what you need, Scala refuses an error message. Thus, a choice had to be made, and Ordering had more opportunities for this.
Du, I forgot to explain why the signature is not defined as ordered[A <% Ordered[A]] , but not ordered[A <: Ordered[A]] . I suspect this will lead to a double implicit failure, which I mentioned earlier, but I will ask the guy who really did this and had double implicit problems whether this particular method is problematic.