Type Class and Subclassing

scala, typeclass

Solution

You should make the type parameter of 'ToString' contravariant:

trait ToString[-T] {
  def toString(t: T): String
}

implicit def ToStr[T: ToString](t: T) = new {
    def toStr: String = implicitly[ToString[T]] toString t
}

class A
implicit object AToString extends ToString[A] {
    def toString(a: A) = "A"
}

(new A).toStr // A

class B extends A
(new B).toStr // A

You can find some detailed information about variance in scala here:

- http://blogs.atlassian.com/2013/01/covariance-and-contravariance-in-scala/

Problem

Suppose I have a type class: ``` trait ToString[T] { def toString(t: T): String } ``` And the following pimp: ``` implicit def ToStr[T: ToString](t: T) = new { def toStr: String = implicitly[ToString[T]] toString t } ``` Now let´s test it: ``` class A implicit object AToString extends ToString[A] { def toString(a: A) = "A" } (new A).toStr // A ``` Fine, so far. But if I introduce a subclass `B` of `A`: ``` class B extends A (new B).toStr // could not find implicit value for evidence parameter of type ToString[B] ``` So I tried: ``` implicit def foo[X: ToString, Y <: X]: ToString[Y] = new ToString[Y] { def toString(y: Y): String = implicitly[ToString[X]] toString y } ``` But then I got: ``` (new B).toStr // diverging implicit expansion for type ToString[...] ``` What can I do to automatically use the type class for the superclass if there isn`t a type class for the subclass available?

Original source