2013-03-24 76 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