Reputation: 28071
Considering this function:
def justTrue[T, S](seq: S)(implicit ev: S <:< Seq[T]) = true
justTrue(List(1,2,3))
>> true
It works. But why can't the same signature be used as a implicit conversion?
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].
Isn't implicit conversion just a function?
Upvotes: 7
Views: 203
Reputation: 11280
Your are completely right, this should work just as well in an implicit def
/class
.
This is a bug where a type parameter accidentally survives type inference from a parameter of an implicit view:
SI-7944: type variables escape into the wild
It is now fixed as of 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
As for workarounds, there are many, you can use higher-kinded as in your answer, or for example force the inference of T
from the seq
parameter:
// 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
Upvotes: 6
Reputation: 28071
The best solution I have found yet:
import scala.language.higherKinds
implicit class TruthTeller[T, S[T] <: Seq[T]](seq: S[T]) {
def justTrue = true
}
List(1,2,3).justTrue
>> true
But I really want to know why the original code doesn't work.
Upvotes: 0