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?