2013-03-24 98 views
3

假设我有一个类型的类:类型类和子类

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

而下面的皮条客:

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

现在let's测试:

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

精细,所以远。但是,如果我介绍BA的子类:

class B extends A 
(new B).toStr // could not find implicit value for evidence parameter of type ToString[B] 

所以,我想:

implicit def foo[X: ToString, Y <: X]: ToString[Y] = new ToString[Y] { 
    def toString(y: Y): String = implicitly[ToString[X]] toString y 
} 

但后来我:

(new B).toStr // diverging implicit expansion for type ToString[...] 

我能做些什么来自动使用类型类对于超类,如果没有可用的子类的类型类?

回答

8

你应该做 '的ToString' 逆变类型参数:

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 

你可以找到斯卡拉约方差一些详细的信息在这里:

+0

也许解释会是为了? – Felix 2013-03-24 17:47:40

+0

@Felix我刚刚添加了一个博客链接,介绍类型差异。 – 2013-03-24 17:53:17

+0

谢谢。当然是逆转的。傻了,尽管我最近读了PinS的相关章节。 – 2013-03-24 18:01:33