Monthly Archives: June 2020

Orthogonal Typeclass In Scala

As an addendum to a previous blog post on the topic of ad-hoc polymorphism in Scala, I’m adding another common typeclass pattern as a separate post. The term “orthogonal” refers to a pattern that selected class attributes are taken out from the base class to form an independent typeclass.

Using an ADT similar to the Car/Sedan/SUV example used in that previous post, we first define trait Car as follows:

Unlike how the base trait was set up as a typeclass in the ad-hoc polymorphism example, trait Car is now an ordinary trait. But the more significant difference is that method setPrice() is no longer in the base class. It’s being constructed “orthogonally” in a designated typeclass:

Similar to how implicit conversions are set up for ad-hoc polymorphism, implicit values are defined within the companion objects for the individual child classes to implement method setPrice() for specific car types.

The specific method implementations are then abstracted into a “unified” method, setNewPrice(), via an implicit constructor argument by passing the Settable typeclass into the CarOps implicit class:

Testing it out:

Putting all method implementations in one place

It’s worth noting that having the implicit values for method implementations defined in the companion objects for the individual classes is just one convenient way. Alternatively, these implicit values could all be defined in one place:

A benefit of putting all method implementations in one place is that new methods can be added without touching the base classes – especially useful in situations where those case classes cannot be altered.

For instance, if color is also an attribute of trait Car and its child case classes, adding a new color setting method will be a trivial exercise by simply adding a setColor() method signature in trait Settable and its specific method implementations as well as setNewColor() within class CarOps.

Orthogonal type collection

Let’s see what a collection of cars looks like:

To refine the inferred List[Product with java.io.Serializable] collection type, we could provide some type hints as shown below: