DEV Community

Cover image for Typeclasses explained in Java
Senjin Hajrulahovic
Senjin Hajrulahovic

Posted on

Typeclasses explained in Java

By definition type classes are a type system construct that supports ad hoc polymorphism.

Let us elaborate this definition by explaining following aspects of type classes:

  • Externalized not implemented inside the class in question
  • Classes which we do not control
  • Possibility to have multiple implementations
  • Lawfullness

An excellent example for showcasing the aforementioned aspects and the differences between the type class approach opposed to the usual inheritance approach are the java interfaces Comparable and Comparator.

External vs internal implementation

In order to use inheritance approach the class which instances we want compare has to extend Comparable and add an implementation for the compareTo method. Opposite to that if we take the type class approach we will implement a Comparator instance.

Classes which we do not control

It's not possible to use the inheritance approach in cases in which we do not have control over the class we want to compare. E.g. the class is pulled from an external dependency.
There are way around that, e.g. defining a wrapper class which can sometimes be inconvenient. The type class approach does not have that restriction. We are free to implement Comparator instance for every class we can our hands on.

Single vs multiple implementations

Using Comparable restricts us to a single Comparable implementation. There are ways around that too, e.g using subclasses and define different implementation for each subclass. Depending on the language we use we can define one or more type class implementations. While scala allows multiple type class implementations, expected they are not defined at the same resolution level. You can read more about it here. Haskell usually does not allow multiple type class instances. Although there are ways to avoid this restriction.

Lawfullness

Every type class comes with a set of laws which every instance needs to abide to. In case of the Comparator type class we have e.g.:

if x.equals(y) then x.compareTo(y) == 0

if x.compareTo(y) == 0 then y.compareTo(x) == 0

if x.compareTo(y) < 0 and y.compareTo(z) < 0
then x.comapreTo(z) < 0
Enter fullscreen mode Exit fullscreen mode

In general this is all there is to type classes. While this is just an example there is a plethora of type classes most of which come from category theory. But you definitely don't need to go into that topic to make use of them. In scala type classes are implemented using traits which are quite close to java interfaces.

When it comes to scalas implementation of type classes the part that confuses people the most seems not to be the actual concept of type classes but the scala implicits magic behind the scenes. The magic is required because, different from haskell which defines type classes as first-class structure
In scala they are not part of the language core, instead they are implemented using other language features such as implicit parameters and implicit conversions. Implicits can sometimes be confusing especially for newcomers, but don't let yourself get discouraged.

As a result the notion of comparing instance of a certain class is externalized. Method definitions using the inheritance approach would look this this:

// java
public <A extends Comparable<A>> ResultType methodWhichNeedsToCompareInstances(A a)
Enter fullscreen mode Exit fullscreen mode
// scala
def methodWhichNeedsToCompareInstances[A <: Comparable[A]](a: A): ResultType
Enter fullscreen mode Exit fullscreen mode

While using the type class approach they would look like this:

// java
public <A> ResultType methodWhichNeedsToCompareInstances(A a)(Comparator<A> comparator)
Enter fullscreen mode Exit fullscreen mode
// scala
def methodWhichNeedsToCompareInstances[A](a: A)
(implicit comparator: Comparator[A]): ResultType
Enter fullscreen mode Exit fullscreen mode

If I managed to gain you interest you can take a look at one of the following libraries like cats, scalaz for scala and vavr for java which contain type class definitions and implementations for common types.

Top comments (0)