Skip to content
Type Classes via Implicits
step 1/5

Reading — step 1 of 5

Learn

~1 min readImplicits and Type Classes

A type class is an interface defined separately from the types that implement it. Combined with implicits, you can retroactively make any type satisfy it.

// 1. Define the type class
trait Show[A] {
    def show(a: A): String
}

// 2. Provide instances for the types you care about
implicit val intShow: Show[Int] = new Show[Int] {
    def show(a: Int): String = s"int: $a"
}

implicit val strShow: Show[String] = new Show[String] {
    def show(a: String): String = s"str: '$a'"
}

// 3. Generic function uses the type class via implicit
def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

display(42)        // "int: 42"
display("hi")      // "str: 'hi'"

Context bound is shorthand for (implicit ev: TypeClass[A]):

def display[A: Show](a: A): String = implicitly[Show[A]].show(a)

This is THE pattern in Scala libraries — Ordering[A], Numeric[A], Ordering[A], Equiv[A]. Spark, Cats, ZIO, Akka — all built on type classes.

Why over inheritance?

  • Add behavior to types you don't own (Java strings, Int, etc.)
  • Multiple instances per type (different orderings, etc.)
  • Compose without forcing every type into a hierarchy

With Scala 3 you'd write:

given Show[Int] with
    def show(a: Int): String = s"int: $a"

— but the underlying machinery is identical.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…