Scala 3 — Book

Type Classes

Language

A type class is an abstract, parameterized type that lets you add new behavior to any closed data type without using sub-typing. If you are coming from Java, you can think of type classes as something like java.util.Comparator[T].

The paper “Type Classes as Objects and Implicits” (2010) by Oliveira et al. discusses the basic ideas behind type classes in Scala. Even though the paper uses an older version of Scala, the ideas still hold to the current day.

This style of programming is useful in multiple use-cases, for example:

  • Expressing how a type you don’t own—such as from the standard library or a third-party library—conforms to such behavior
  • Adding behavior to multiple types without introducing sub-typing relationships between those types (i.e., one extends another)

In Scala 3, type classes are just traits with one or more type parameters, like the following:

trait Show[A]:
  def show(a: A): String

Instances of Show for a particular type A witness that we can show (i.e., produce a text representation of) an instance of type A. For example, let’s look at the following Show instance for Int values:

class ShowInt extends Show[Int]:
  def show(a: Int) = s"The number is ${a}!"

We can write methods that work on arbitrary types A constrained by Show as follows:

def toHtml[A](a: A)(showA: Show[A]): String =
  "<p>" + showA.show(a) + "</p>"

That is, toHtml can be called with arbitrary A as long as you can also provide an instance of Show[A]. For example, we can call it like:

toHtml(42)(ShowInt())
// results in "<p>The number is 42!</p>"

Automatically passing type class instances

Since type classes are a very important way to structure software, Scala 3 offers additional features that make working with them very convenient. We discuss these additional features (which fall into the category of Contextual Abstractions) in a later chapter of this book.

Contributors to this page: