Many people coming from Java ask what type classes are, why are they used, and how. This post is not intended to explain how to fully implement type classes, but to show a down to earth example, the name-printer.

In a previous post, Scala Object Serialization for MapR-DB, we used a simple type class to solve the serialization problem we encountered when using MapR-DB from our beloved Scala. Now, we are presenting an even simpler example to show the why and how of type classes.

The Name Representation

Let’s start by stating the problem in question. In this case, we have a business object called Name and it represents, as you might guess, a person’s name. We can represent someone’s name by using the following class.

Now, the question is how do we want to represent this object once we have that need?

For those coming from Java, the answer is simple, we need to override the .toString function and problem solved. It is, actually, most complex than that.

The same name can be represented differently depending on a specific context. For example, Nicola A Perez can be Mr. Perez in a formal context, or it might be Nico in a very social environment. The exact same name might have to be fully addressed sometimes, and other time (web id) it can just be anicolaspp .

If we try to attach the representations to the Name object itself, we certainly are going to be short every time since there will always be a context we did not take in consideration.

The idea is to decouple the object and its possible representations while enabling a polymorphic mechanism to tight them back together when needed, even we if we don’t have access to the original source code of the class itself.

The Printable Type Class

We can start by defining a trait that represents the type class we are going to use in this example.

In the above snippet, we have defined the interface to our possible representations and now let’s see how we could implement some of them.

As we can see, we have added multiple ways to represent a name. Now we can use each of them in a different context. Let’s define some functions where each of them receives a name and prints it. Notice that each function represents the context itself.