So I have been learning Scala for the past month, and yesterday I was playing around in the REPL with simple sorting algorithms. Using the standard functional quicksort, it's easy to make a sort function polymorphic in the element type, but it got me thinking: what if I could make it polymorphic in the type of data structure as well? It's annoying to have separate functions for List
,Vector
,etc. Of course, I could have it just take a Seq[E]
, but then there seems to be no guarantee as to the underlying implementation of that Seq[E]
. All the linear collections implement Seq
, which has all the functions we need(filter
, apply
, and append
) so we should be able to have one function that can sort all linear collections, right? I came up with the following code:
object QSort {
def qsort[E, D[E] <: Seq[E]](s: D[E])(c: (E, E) => Int): D[E] = {
if (s.length <= 1) s
else {
val pivot: E = s(s.length / 2)
qsort[E, D](s.filter((x: E) => c(x, pivot) < 0))(c)
.append(s.filter((x: E) => c(x, pivot) == 0))
.append(qsort[E, D](s.filter((x: E) => c(x, pivot) > 0))(c))
}
}
}
which takes some data structure D[E]
that is a subclass of Seq[E]
and a comparator function and should apply a highly inefficient quicksort. However, the compiler says that when I call filter
, there is a type mismatch since filter returns a Seq[E]
and not a D[E]
. Why does filter
not return a D[E]
, and is this kind of polymorphism even actually possible?