Implicit conversion vs. type class

While I don’t want to duplicate my material from Scala In Depth, I think it’s worth noting that type classes / type traits are infinitely more flexible.

def foo[T: TypeClass](t: T) = ...

has the ability to search its local environment for a default type class. However, I can override default behavior at any time by one of two ways:

  1. Creating/importing an implicit type class instance in Scope to short-circuit implicit lookup
  2. Directly passing a type class

Here’s an example:

def myMethod(): Unit = {
   // overrides default implicit for Int
   implicit object MyIntFoo extends Foo[Int] { ... }
   foo(5)
   foo(6) // These all use my overridden type class
   foo(7)(new Foo[Int] { ... }) // This one needs a different configuration
}

This makes type classes infinitely more flexible. Another thing is that type classes / traits support implicit lookup better.

In your first example, if you use an implicit view, the compiler will do an implicit lookup for:

Function1[Int, ?]

Which will look at Function1‘s companion object and the Int companion object.

Notice that Quantifiable is nowhere in the implicit lookup. This means you have to place the implicit view in a package object or import it into scope. It’s more work to remember what’s going on.

On the other hand, a type class is explicit. You see what it’s looking for in the method signature. You also have an implicit lookup of

Quantifiable[Int]

which will look in Quantifiable‘s companion object and Int‘s companion object. Meaning that you can provide defaults and new types (like a MyString class) can provide a default in their companion object and it will be implicitly searched.

In general, I use type classes. They are infinitely more flexible for the initial example. The only place I use implicit conversions is when using an API layer between a Scala wrapper and a Java library, and even this can be ‘dangerous’ if you’re not careful.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)