(I'm using Scala nightlies, and see the same behaviour in 2.8.0b1 RC4. I'm a Scala newcomer.)
I have two SortedMap
s that I'd like to form the union of. Here's the code I'd like to use:
import scala.collection._
object ViewBoundExample {
class X
def combine[Y](a: SortedMap[X, Y], b: SortedMap[X, Y]): SortedMap[X, Y] = {
a ++ b
}
implicit def orderedX(x: X): Ordered[X] = new Ordered[X] { def compare(that: X) = 0 }
}
The idea here is the 'implicit' statement means X
s can be converted to Ordered[X]
s, and then it makes sense combine SortedMap
s into another SortedMap
, rather than just a map.
When I compile, I get
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac -versionScala compiler version
2.8.0.Beta1-RC4 -- Copyright 2002-2010, LAMP/EPFL
sieversii:scala-2.8.0.Beta1-RC4 scott$ bin/scalac ViewBoundExample.scala
ViewBoundExample.scala:8: error: type arguments [ViewBoundExample.X] do not
conform to method ordered's type parameter bounds [A <: scala.math.Ordered[A]]
a ++ b
^
one error found
It seems my problem would go away if that type parameter bound was [A <% scala.math.Ordered[A]]
, rather than [A <: scala.math.Ordered[A]]
. Unfortunately, I can't even work out where the method 'ordered' lives! Can anyone help me track it down?
Failing that, what am I meant to do to produce the union of two SortedMap
s? If I remove the return type of combine (or change it to Map
) everything works fine --- but then I can't rely on the return being sorted!
Currently, what you are using is the
scala.collection.SortedMap
trait, whose++
method is inherited from theMapLike
trait. Therefore, you see the following behaviour:The type of the return result of
++
is aMap[Int, Int]
, because this would be the only type it makes sense the++
method of aMapLike
object to return. It seems that++
keeps the sorted property of theSortedMap
, which I guess it is because++
uses abstract methods to do the concatenation, and those abstract methods are defined as to keep the order of the map.To have the union of two sorted maps, I suggest you use
scala.collection.immutable.SortedMap
.This implementation of the
SortedMap
trait declares a++
method which returns aSortedMap
.Now a couple of answers to your questions about the type bounds:
Ordered[T]
is a trait which if mixed in a class it specifies that that class can be compared using<
,>
,=
,>=
,<=
. You just have to define the abstract methodcompare(that: T)
which returns-1
forthis < that
,1
forthis > that
and0
forthis == that
. Then all other methods are implemented in the trait based on the result ofcompare
.T <% U
represents a view bound in Scala. This means that typeT
is either a subtype ofU
or it can be implicitly converted toU
by an implicit conversion in scope. The code works if you put<%
but not with<:
asX
is not a subtype ofOrdered[X]
but can be implicitly converted toOrdered[X]
using theOrderedX
implicit conversion.Edit: Regarding your comment. If you are using the
scala.collection.immutable.SortedMap
, you are still programming to an interface not to an implementation, as the immutableSortedMap
is defined as atrait
. You can view it as a more specialised trait ofscala.collection.SortedMap
, which provides additional operations (like the++
which returns aSortedMap
) and the property of being immutable. This is in line with the Scala philosophy - prefer immutability - therefore I don't see any problem of using the immutableSortedMap
. In this case you can guarantee the fact that the result will definitely be sorted, and this can't be changed as the collection is immutable.Though, I still find it strange that the
scala.collection.SortedMap
does not provide a++
method witch returns aSortedMap
as a result. All the limited testing I have done seem to suggest that the result of a concatenation of twoscala.collection.SortedMap
s indeed produces a map which keeps the sorted property.