2013-12-22 159 views
7

考慮到這一功能:泛型類型的隱式轉換?

def justTrue[T, S](seq: S)(implicit ev: S <:< Seq[T]) = true 
justTrue(List(1,2,3)) 
>> true 

它的工作原理。但爲什麼不能將相同的簽名用作隱式轉換?

implicit class TruthTeller[T, S](seq: S)(implicit ev: S <:< Seq[T]) { 
    def justTrue = true 
} 
List(1,2,3).justTrue 
>> error: Cannot prove that List[Int] <:< Seq[T]. 

是不是隱式轉換隻是一個函數?

+0

確實很奇怪。 'val a = new TruthTeller(List(1,2,3))'可以。當你移除'type T'並使用'imp ev:S <: Kigyo

+0

這也正是我問這個問題的原因。我找到了一種解決方法(請參閱下面的答案),但我希望能夠解釋爲什麼原始代碼無法正常工作。 –

回答

6

你是完全正確的,這應該也可以在隱含的def/class中工作。

這是一個類型參數無意中從存活的隱式視圖的參數類型推斷一個錯誤:

SI-7944: type variables escape into the wild

它現在固定爲2.11.0-M7的:

Welcome to Scala version 2.11.0-M7 (OpenJDK 64-Bit Server VM, Java 1.7.0_45). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> :pa 
// Entering paste mode (ctrl-D to finish) 
implicit class TruthTeller[T, S](seq: S)(implicit ev: S <:< Seq[T]) { 
    def justTrue = true 
} 
List(1,2,3).justTrue 
// Exiting paste mode, now interpreting. 

defined class TruthTeller 
res0: Boolean = true 

至於變通方法有很多,您可以在答案中使用higher-kinded,或者例如從seq參數中強制推薦T

// the implicit ev isn't even needed here anymore 
// but I am assuming the real use case is more complex 
implicit class TruthTeller[T, S](seq: S with Seq[T])(implicit ev: S <:< Seq[T]) { 
    def justTrue = true 
} 
// S will be inferred as List[Int], and T as Int 
List(1,2,3).justTrue 
+0

感謝您指出這是一個錯誤! –

0

最好的解決辦法,我發現尚未:

import scala.language.higherKinds 
implicit class TruthTeller[T, S[T] <: Seq[T]](seq: S[T]) { 
    def justTrue = true 
} 
List(1,2,3).justTrue 
>> true 

但我真的想知道爲什麼原來的代碼無法正常工作。