I\'ve been reading up on type classes in Scala and thought I had a good grasp on it, until I remembered Java\'s java.util.Comparator
.
If I understand proper
The term type class comes from Haskell were they are part of the language. In scala, it is not, it is more of a pattern, which happens to have a lot of language support in scala (implicits, mostly). The pattern makes sense even without this syntactic support, for instance in java, and I would say that Comparator
is a typical example of that pattern there (although the term type class is not used in java).
From an object oriented perspective, the pattern consist in having Comparator
rather than Comparable
. The most basic object thinking would have the comparison service in the object, say class String implements Comparable
. However, extracting it has numerous advantages:
These two reasons are enough to have Comparable
in java, and to use them in in sorted collections (e.g TreeSet
) Comparable
is kept, as it gives a convenient default (no need to pass a Comparator when you want the "default" comparison, and it is easier to call (x.compareTo(y) rather than comparator.compare(x,y)). In scala, with implicits, none of this reason is compelling (interoperability with java would still be a reason to implement Ordered/Comparable in scala).
There are other, less obvious advantages to type classes. Among them :
sum(list)
. It requires that there is some sort of addition available on the elements of the list. This might be available in the element themselves. Say they could be some Addable[T]
with def add(other: T): T
. But if you pass the empty list to sum, it should return the "zero" of the type of the type of the list (0 for ints, the empty string for strings...). Having a def zero: T
in Addable[T]
would be useless, as at that moment, you have no Addable
around. But this works fine with a type class such as Numeric
or Monoid
. Int
and String
to have an ordering defined on the pair (Int, String)
, or given an Ordering
on T
, build an ordering on List[T]
. Scala does that with implicits, but it still makes sense in java, explicitly. A more sophisticated example:
// Comparison by the first comparator which finds the two elements different.
public static Comparator lexicographic(final Comparator... comparators) {
return new Comparator() {
public int compare(T t1, T t2) {
for(comparator : comparators) {
int result = comparator.compare(t1, t2);
if (result != 0) return result;
}
return 0;
}
}
}
(might be simpler in scala, but again, this is of interest in java)
There are some small disadvantages too (much more so in java than in scala, but still)
if(x is Comparable>) {do some sorting}
,
this would not be possible with a Comparator.