Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion for generic type?

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?

like image 712
Lai Yu-Hsuan Avatar asked Dec 22 '13 12:12

Lai Yu-Hsuan


People also ask

Is it possible to inherit from a generic type?

You can't inherit from the generic type parameter. C# generics are very different from C++ templates. Inheriting from the type parameter requires the class to have a completely different representation based on the type parameter, which is not what happens with . NET generics.

How do you know if a type is generic?

Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.

What is generic type constraint?

A type constraint on a generic type parameter indicates a requirement that a type must fulfill in order to be accepted as a type argument for that type parameter. (For example, it might have to be a given class type or a subtype of that class type, or it might have to implement a given interface.)


1 Answers

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
like image 121
gourlaysama Avatar answered Oct 04 '22 05:10

gourlaysama