4

While working on this question, I came up with the following issue. Consider two method definitions:

def foo[T <: Ordered[T]](s : Seq[T]) = s.sorted

def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted

The first one compiles, the second does not. The compiler does not figure out that it can use the asserted implicit conversion to get an Ordering. If we help a bit, it works:

def foo[T <% Ordered[T]](s : Seq[T]) = s.sortWith(_<=_)

While compiling the anonymous function the compiler applies the implicit conversion to find method <=, everything is fine.

I do not have another example, but can imagine similar issues to happen with other functions on collections that require elements to have certain properties, if those can only be asserted via conversion.

Is there a particular reason why the compiler is restricted this way? Is there no general way to resolve such issues? (Here it seems easy.) Is there a workaround, e.g. another implicit conversion that translates the property on Key[T] to T?

(Note that the last idea can be problematic if a concrete value for T ends up having the property; we then get an ambiguous situation).

Community
  • 1
  • 1
Raphael
  • 9,779
  • 5
  • 63
  • 94

2 Answers2

4
scala> implicit def ordering[T <% Ordered[T]] = new Ordering[T]{def compare(x: T, y: T) = x compare y}
ordering: [T](implicit evidence$1: (T) => Ordered[T])java.lang.Object with Ordering[T]

scala> def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
foo: [T](s: Seq[T])(implicit evidence$1: (T) => Ordered[T])Seq[T]
IttayD
  • 28,271
  • 28
  • 124
  • 178
  • Valid solution for 2.8.1-final, thanks. I guess there is no general way, given that you'd have to have a special type describing the special element property (here `Ordering`) for each scenario? – Raphael Feb 03 '11 at 12:57
  • Note that a thusly defined ordering will even be used if `T <: Ordered[T]`. Apparently, implicits are resolved statically. – Raphael Feb 03 '11 at 13:27
3
% scala29
Welcome to Scala version 2.9.0.r24168-b20110202012927 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def foo[T <% Ordered[T]](s : Seq[T]) = s.sorted
foo: [T](s: Seq[T])(implicit evidence$1: (T) => Ordered[T])Seq[T]

scala>

By the way, re "here it seems easy", it wasn't. Implicits like these enjoy diverging and they were pretty determined.

psp
  • 12,138
  • 1
  • 41
  • 51
  • So it is solved in 2.9, cool. Can you please give one or two key arguments why it would not be easy? What happens if also `T <: Ordered[T]`, will the `compare` reachable withouth implicits be preferred? – Raphael Feb 03 '11 at 09:45
  • It's not that easy to explain. Basically, cycles develop and it is very touchy to unravel them. In the library there are many competing concerns as well; a tiny alteration can (as but one example) influence the type inference behavior for some function where people won't want to see it change. Etc. – psp Feb 04 '11 at 05:15