Let's use a real world example. A string parser type class whose implicit instances are created by a function that delegates the creation to a factory.
import scala.reflect.runtime.universe.TypeTag
object Test {
trait Parser[+T] { def parse(input: String): T }
implicit def summonParserOf[T](implicit factory: ParserFactory[T]): Parser[T] = factory.build
trait ParserFactory[T] { def build: Parser[T] }
implicit def summonFactoryOfParsersOf[T](implicit t: TypeTag[T]): ParserFactory[T] =
new ParserFactory[T] {
def build: Parser[T] = new Parser[T] {
def parse(input: String) = {
println("T = " + t.tpe) // this outputs "T = Int" if Parser is non variant, and "T = Nothing" if Parser is covariant on T. Why?
null.asInstanceOf[T]
}
}
}
def main(args: Array[String]): Unit = {
val parserOfInt = implicitly[Parser[Int]]
parserOfInt.parse("")
}
}
The type parameter T received by the factory is Int when Parser is non-variant, and Nothing when it is covariant. Why?
Edit 1:
The factory is not necessary. The replacement occurs before. So the test can be reduced to:
package jsfacile.test
import scala.reflect.runtime.universe.TypeTag
object Probando {
trait Parser[+T] { def parse(input: String): T }
implicit def summonParserOf[T](implicit t: TypeTag[T]): Parser[T] = new Parser[T] {
def parse(input: String): T = {
println("summon parser: T = " + t.tpe) // this outputs "T = Int" if Parser is non variant, and "T = Nothing" if Parser is covariant on T. Why?
null.asInstanceOf[T]
null.asInstanceOf[T]
}
}
def main(args: Array[String]): Unit = {
val parserOfInt = implicitly[Parser[Int]]
parserOfInt.parse("")
}
}
Parser[Nothing] is assignable to Parser[Int], but which is the purpose of choosing the lower bound instead of the upper one?
Edit 2: The answer given by #Dmytro Mitin and the useful comments below, translated to my own words and limited scope of thinking, for future reference to myself.
What stopped me to understand was the wrong idea that, when the implicit value provider is a def with parametrized result type, there is no set of living values from which the compiler has to pick one of. In that case, I thought, it just skips that step (the one that chooses the value with the most specific declared type).
And given the summoner function grants the compiler the power to build a value of any type, why not to fill the implicit parameter with a value that makes him happy. If the implicit parameter demands something assignable to a type T then give it a value of type T. Giving it Nothing, which is assignable to everything, wouldn't be nice nor useful.
The problem with that idea arises when there is more than one summoner providing values assignable to the implicit parameter type. In that case, the only consistent way to decide which summoner to chose is to deduce the set of types of the values they produce, pick a type from said set based on an established criteria (the most specific, for instance), and choose the summoner that produces it.
Scala spec says
If there are several eligible arguments which match the implicit parameter's type, a most specific one will be chosen using the rules of static overloading resolution
https://scala-lang.org/files/archive/spec/2.11/07-implicits.html#implicit-parameters
Since you defined instances like
implicit def summonParserOf[T](implicit t: TypeTag[T]): Parser[T] = ...
for covariant
trait Parser[+T] { ... }
when you look for implicitly[Parser[T]], all summonParserOf[S] (S <: T) are eligible candidates, so the compiler selects the most specific one.
I'm trying to create a trait that would provide the name of the abstract type that is added in the sub-class:
trait T {
type T
def myClassOf[T:ClassTag] = implicitly[ClassTag[T]].runtimeClass
def getType = {
myClassOf[T].getSimpleName
}
}
class TT extends T {
type T = String
}
However, this fails to compile:
Error:(7, 15) not enough arguments for method myClassOf: (implicit evidence$1: scala.reflect.ClassTag[T.this.T])Class[_].
Unspecified value parameter evidence$1.
myClassOf[T].getSimpleName
^
But it works fine if I move the getType method to the sub-class. Can someone explain why and whether there is a way to do this call from the sub-class?
At the point where you call myClassOf[T] T is still abstract, so the compiler can not generate a ClassTag for it. You can fix it by delaying the generation of the ClassTag[T] until T is known.
trait Trait {
type T
def myClassOf[A:ClassTag] = implicitly[ClassTag[A]].runtimeClass
def getType(implicit tag: ClassTag[T]) = {
myClassOf[T].getSimpleName
}
}
class Sub extends Trait {
type T = String
}
If adding an implicit parameter is impossible for some reason I think the best way is probably requiring some method getClassT to be implemented in subclasses. Since its return type is Class[T] it's difficult to provide a wrong implementation in a subclass.
trait Trait {
type T
def getType = {
getClassT.getSimpleName
}
def getClassT: Class[T]
}
class Sub extends Trait {
type T = String
def getClassT = classOf[T]
}
Note that the above answers, while good are now obsolete as of scala 2.10.
the preferred method now is to use TypeTag or ClassTag.
As described in the docs (see below) you can now use them in implicit param lists or context bounds to do this kind of thing:-
import scala.reflect.runtime.universe._
def paramInfo[T: TypeTag](x: T): Unit = {
val targs = typeOf[T] match { case TypeRef(_, _, args) => args }
println(s"type of $x has type arguments $targs")
}
scala> paramInfo(42)
type of 42 has type arguments List()
scala> paramInfo(List(1, 2))
type of List(1, 2) has type arguments List(Int)
see scala docs on Typetags
see api docs
I have a Number Wrapper like this
class NumWrapper[A<:AnyVal](var v: A)(implicit n:Numeric[A]) {
def +(other: A): NumWrapper[A] = {
new NumWrapper(n.plus(v, other))
}
def -(other: A): NumWrapper[A] = {
new NumWrapper(n.minus(v, other))
}
}
All work fine. But when I want to have the implicit conversion, i create a companion class as followed:
object NumWrapper {
implicit def toNumWrapper[A<:AnyVal](v: A) = new NumWrapper[A](v)
}
But I have the error at compilation:
could not find implicit value for parameter n: Numeric[A]
What is wrong here ? Why it is trying to find the implicit match for type A at compilation?
Thank you very much for your help.
Implicit checks in Scala are performed at compile time (it is a statically typed language). If the compiler can't identify a single, unambiguous, matching implicit value that will be available at the calling location, it complains.
One way you can fix this here is to add the implicit requirement to the toNumWrapper method:
object NumWrapper {
implicit def toNumWrapper[A<:AnyVal](v: A)(implicit n:Numeric[A]) = new NumWrapper[A](v)
}
This pushes the requirment for an implicit Numeric out to the location where the implicit conversion is required, eg, in the console, I could then write:
scala> val chk1 = 3L
chk1: Long = 3
scala> val chk2 = NumWrapper.toNumWrapper(chk1)
chk2: NumWrapper[Long] = NumWrapper#1e89017a
And the compiler is happy because (I think - not entirely sure of this) the Long value carries its own implicit Numeric[Long] with it.
According your code,
class NumWrapper[A<:AnyVal](var v: A)(implicit n:Numeric[A])
to call new NumWrapper[MyType](v) a Numeric[MyType] must be in the scope of implicit resolution.
So when you have
object NumWrapper {
implicit def toNumWrapper[A<:AnyVal](v: A) = new NumWrapper[A](v)
}
which is calling this NumWrapper constructor, the Numeric[A] must resolved. That's not the case and the compiler raise the mentioned error.
I'm beginner in scala and don't understand what happend here :
Given :
val reverse:Option[MyObject] = ...
And myObject.isNaire return Boolean.
If I do :
val v:Option[Boolean] = reverse.map(_.isNaire)
val b:Boolean = v.getOrElse(false)
It work.
Now, If I do :
val b:Boolean = reverse.map(_.isNaire).getOrElse(false)
It fail to compile with a type mismatch: found Any, required Boolean
Edit : Thanks Beryllium, by making SSCCE, I found a beginning of explication. In the first example, myObject is a java class, so isNaire is a java.lang.Boolean. I thought implicit conversion should make this transparent so the explanation is still welcome.
class Test(val naire:java.lang.Boolean)
class Other {
val testValue = Some(new Test(true))
def mysteriousCompilationError:Boolean = testValue.map(_.naire).getOrElse(false)
}
Note: ScalaCompiler is 2.10.2
In the scala.Predef there's an implicit conversion from java.lang.Boolean to scala.Boolean:
implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue
So in your first case val v:Option[Boolean] = reverse.map(_.isNaire) the compiler see's a java.lang.Boolean and looks for an implicit method in scope to convert it to a scala.Boolean, which it conveniently finds in scala.Predef.
In you're second case, testValue.map(_.naire).getOrElse(false), the compiler is doing things in this order:
Option[Test] => Option[java.lang.Boolean]
getOrElse[B >: A](default: => B): B where A is java.lang.Boolean and B is Any since scala.Boolean is not >: java.lang.Boolean
val b:Boolean, compiler can't find an implicit conversion from Any to scala.Boolean
The only way to get around this, is to tell the compiler during the map operation to use the implicit conversion from scala.Predef to go from java.lang.Boolean to scala.Boolean:
def works:Boolean = testValue.map[Boolean](_.naire).getOrElse(false)
This is a common problem and pops up often since map followed by getOrElse is very convienent. To properly fix this without the extra types, use a fold (catamorphism) over the option:
def worksToo:Boolean = testValue.fold(false)(_.naire)
By using fold you get some added type safety since there's no conversion down to common types. For instance, you can't do this:
def failsTypeCheck = testValue.fold("test")(_.naire)
While the compiler has no problem with this:
def passesTypeCheck = testValue.map(_.naire).getOrElse("test")
java.lang.Boolean and scala.Boolean is not the same. To bridge the gap you have to provide a location where the implicit conversion can do it's work.
There are some patterns to handle these types of Java/Scala interoperability problems:
If it's OK to have a different method to be used from the Scala side, you could use an implicit value class:
object Container {
implicit class Test2Scala(val test: Test) extends AnyVal {
def naireForScala: Boolean = test.naire
}
}
class Other {
val testValue = Some(new Test(true))
import Container._
def mysteriousCompilationError: Boolean =
testValue.map(_.naireForScala).getOrElse(false)
}
This does not require additional instances at run-time. It just provides another method to enrich the Java class.
If you can derive a sub class, you could preserve the method's name by using a DummyImplicit:
class Test2(_naire: Boolean) extends Test(_naire) {
def naire(implicit di: DummyImplicit): Boolean = _naire
}
class Other {
val testValue = Some(new Test2(true))
def mysteriousCompilationError: Boolean =
testValue.map(_.naire).getOrElse(false)
}
The DummyImplicit is required to get a different method signature. It's a bit tricky, requires an additional instance at run-time, but Test2 is a Test (in terms of OOP).
Wrap the Java instance in a Scala instance:
class TestWrapper(test: Test) {
def naire: Boolean = test.naire
}
class Other {
val testValue = Some(new TestWrapper(new Test(true)))
def mysteriousCompilationError: Boolean =
testValue.map(_.naire).getOrElse(false)
}
Requires an additional instance, you have to add delegates, TestWrapper is not a Test, but it's simple.
I wrote this in scala and it won't compile:
class TestDoubleDef{
def foo(p:List[String]) = {}
def foo(p:List[Int]) = {}
}
the compiler notify:
[error] double definition:
[error] method foo:(List[String])Unit and
[error] method foo:(List[Int])Unit at line 120
[error] have same type after erasure: (List)Unit
I know JVM has no native support for generics so I understand this error.
I could write wrappers for List[String] and List[Int] but I'm lazy :)
I'm doubtful but, is there another way expressing List[String] is not the same type than List[Int]?
Thanks.
I like Michael Krämer's idea to use implicits, but I think it can be applied more directly:
case class IntList(list: List[Int])
case class StringList(list: List[String])
implicit def il(list: List[Int]) = IntList(list)
implicit def sl(list: List[String]) = StringList(list)
def foo(i: IntList) { println("Int: " + i.list)}
def foo(s: StringList) { println("String: " + s.list)}
I think this is quite readable and straightforward.
[Update]
There is another easy way which seems to work:
def foo(p: List[String]) { println("Strings") }
def foo[X: ClassTag](p: List[Int]) { println("Ints") }
def foo[X: ClassTag, Y: ClassTag](p: List[Double]) { println("Doubles") }
For every version you need an additional type parameter, so this doesn't scale, but I think for three or four versions it's fine.
[Update 2]
For exactly two methods I found another nice trick:
def foo(list: => List[Int]) = { println("Int-List " + list)}
def foo(list: List[String]) = { println("String-List " + list)}
Instead of inventing dummy implicit values, you can use the DummyImplicit defined in Predef which seems to be made exactly for that:
class TestMultipleDef {
def foo(p:List[String]) = ()
def foo(p:List[Int])(implicit d: DummyImplicit) = ()
def foo(p:List[java.util.Date])(implicit d1: DummyImplicit, d2: DummyImplicit) = ()
}
To understand Michael Krämer's solution, it's necessary to recognize that the types of the implicit parameters are unimportant. What is important is that their types are distinct.
The following code works in the same way:
class TestDoubleDef {
object dummy1 { implicit val dummy: dummy1.type = this }
object dummy2 { implicit val dummy: dummy2.type = this }
def foo(p:List[String])(implicit d: dummy1.type) = {}
def foo(p:List[Int])(implicit d: dummy2.type) = {}
}
object App extends Application {
val a = new TestDoubleDef()
a.foo(1::2::Nil)
a.foo("a"::"b"::Nil)
}
At the bytecode level, both foo methods become two-argument methods since JVM bytecode knows nothing of implicit parameters or multiple parameter lists. At the callsite, the Scala compiler selects the appropriate foo method to call (and therefore the appropriate dummy object to pass in) by looking at the type of the list being passed in (which isn't erased until later).
While it's more verbose, this approach relieves the caller of the burden of supplying the implicit arguments. In fact, it even works if the dummyN objects are private to the TestDoubleDef class.
Due to the wonders of type erasure, the type parameters of your methods' List get erased during compilation, thus reducing both methods to the same signature, which is a compiler error.
As Viktor Klang already says, the generic type will be erased by the compiler. Fortunately, there's a workaround:
class TestDoubleDef{
def foo(p:List[String])(implicit ignore: String) = {}
def foo(p:List[Int])(implicit ignore: Int) = {}
}
object App extends Application {
implicit val x = 0
implicit val y = ""
val a = new A()
a.foo(1::2::Nil)
a.foo("a"::"b"::Nil)
}
Thanks for Michid for the tip!
If I combine Daniels response and Sandor Murakozis response here I get:
#annotation.implicitNotFound(msg = "Type ${T} not supported only Int and String accepted")
sealed abstract class Acceptable[T]; object Acceptable {
implicit object IntOk extends Acceptable[Int]
implicit object StringOk extends Acceptable[String]
}
class TestDoubleDef {
def foo[A : Acceptable : Manifest](p:List[A]) = {
val m = manifest[A]
if (m equals manifest[String]) {
println("String")
} else if (m equals manifest[Int]) {
println("Int")
}
}
}
I get a typesafe(ish) variant
scala> val a = new TestDoubleDef
a: TestDoubleDef = TestDoubleDef#f3cc05f
scala> a.foo(List(1,2,3))
Int
scala> a.foo(List("test","testa"))
String
scala> a.foo(List(1L,2L,3L))
<console>:21: error: Type Long not supported only Int and String accepted
a.foo(List(1L,2L,3L))
^
scala> a.foo("test")
<console>:9: error: type mismatch;
found : java.lang.String("test")
required: List[?]
a.foo("test")
^
The logic may also be included in the type class as such (thanks to jsuereth):
#annotation.implicitNotFound(msg = "Foo does not support ${T} only Int and String accepted")
sealed trait Foo[T] { def apply(list : List[T]) : Unit }
object Foo {
implicit def stringImpl = new Foo[String] {
def apply(list : List[String]) = println("String")
}
implicit def intImpl = new Foo[Int] {
def apply(list : List[Int]) = println("Int")
}
}
def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
Which gives:
scala> #annotation.implicitNotFound(msg = "Foo does not support ${T} only Int and String accepted")
| sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: type mismatch;
found : Int(1)
required: List[?]
foo(1)
^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:32: error: Foo does not support Double only Int and String accepted
foo(List(1.0))
^
Note that we have to write implicitly[Foo[A]].apply(x) since the compiler thinks that implicitly[Foo[A]](x) means that we call implicitly with parameters.
There is (at least one) another way, even if it is not too nice and not really type safe:
import scala.reflect.Manifest
object Reified {
def foo[T](p:List[T])(implicit m: Manifest[T]) = {
def stringList(l: List[String]) {
println("Strings")
}
def intList(l: List[Int]) {
println("Ints")
}
val StringClass = classOf[String]
val IntClass = classOf[Int]
m.erasure match {
case StringClass => stringList(p.asInstanceOf[List[String]])
case IntClass => intList(p.asInstanceOf[List[Int]])
case _ => error("???")
}
}
def main(args: Array[String]) {
foo(List("String"))
foo(List(1, 2, 3))
}
}
The implicit manifest paramenter can be used to "reify" the erased type and thus hack around erasure. You can learn a bit more about it in many blog posts,e.g. this one.
What happens is that the manifest param can give you back what T was before erasure. Then a simple dispatch based on T to the various real implementation does the rest.
Probably there is a nicer way to do the pattern matching, but I haven't seen it yet. What people usually do is matching on m.toString, but I think keeping classes is a bit cleaner (even if it's a bit more verbose). Unfortunately the documentation of Manifest is not too detailed, maybe it also has something that could simplify it.
A big disadvantage of it is that it's not really type safe: foo will be happy with any T, if you can't handle it you will have a problem. I guess it could be worked around with some constraints on T, but it would further complicate it.
And of course this whole stuff is also not too nice, I'm not sure if it worth doing it, especially if you are lazy ;-)
Instead of using manifests you could also use dispatchers objects implicitly imported in a similar manner. I blogged about this before manifests came up: http://michid.wordpress.com/code/implicit-double-dispatch-revisited/
This has the advantage of type safety: the overloaded method will only be callable for types which have dispatchers imported into the current scope.
Nice trick I've found from http://scala-programming-language.1934581.n4.nabble.com/disambiguation-of-double-definition-resulting-from-generic-type-erasure-td2327664.html
by Aaron Novstrup
Beating this dead horse some more...
It occurred to me that a cleaner hack is to use a unique dummy type
for each method with erased types in its signature:
object Baz {
private object dummy1 { implicit val dummy: dummy1.type = this }
private object dummy2 { implicit val dummy: dummy2.type = this }
def foo(xs: String*)(implicit e: dummy1.type) = 1
def foo(xs: Int*)(implicit e: dummy2.type) = 2
}
[...]
I tried improving on Aaron Novstrup’s and Leo’s answers to make one set of standard evidence objects importable and more terse.
final object ErasureEvidence {
class E1 private[ErasureEvidence]()
class E2 private[ErasureEvidence]()
implicit final val e1 = new E1
implicit final val e2 = new E2
}
import ErasureEvidence._
class Baz {
def foo(xs: String*)(implicit e:E1) = 1
def foo(xs: Int*)(implicit e:E2) = 2
}
But that will cause the compiler to complain that there are ambiguous choices for the implicit value when foo calls another method which requires an implicit parameter of the same type.
Thus I offer only the following which is more terse in some cases. And this improvement works with value classes (those that extend AnyVal).
final object ErasureEvidence {
class E1[T] private[ErasureEvidence]()
class E2[T] private[ErasureEvidence]()
implicit def e1[T] = new E1[T]
implicit def e2[T] = new E2[T]
}
import ErasureEvidence._
class Baz {
def foo(xs: String*)(implicit e:E1[Baz]) = 1
def foo(xs: Int*)(implicit e:E2[Baz]) = 2
}
If the containing type name is rather long, declare an inner trait to make it more terse.
class Supercalifragilisticexpialidocious[A,B,C,D,E,F,G,H,I,J,K,L,M] {
private trait E
def foo(xs: String*)(implicit e:E1[E]) = 1
def foo(xs: Int*)(implicit e:E2[E]) = 2
}
However, value classes do not allow inner traits, classes, nor objects. Thus also note Aaron Novstrup’s and Leo’s answers do not work with a value classes.
I didn't test this, but why wouldn't an upper bound work?
def foo[T <: String](s: List[T]) { println("Strings: " + s) }
def foo[T <: Int](i: List[T]) { println("Ints: " + i) }
Does the erasure translation to change from foo( List[Any] s ) twice, to foo( List[String] s ) and foo( List[Int] i ):
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ108
I think I read that in version 2.8, the upper bounds are now encoded that way, instead of always an Any.
To overload on covariant types, use an invariant bound (is there such a syntax in Scala?...ah I think there isn't, but take the following as conceptual addendum to the main solution above):
def foo[T : String](s: List[T]) { println("Strings: " + s) }
def foo[T : String2](s: List[T]) { println("String2s: " + s) }
then I presume the implicit casting is eliminated in the erased version of the code.
UPDATE: The problem is that JVM erases more type information on method signatures than is "necessary". I provided a link. It erases type variables from type constructors, even the concrete bound of those type variables. There is a conceptual distinction, because there is no conceptual non-reified advantage to erasing the function's type bound, as it is known at compile-time and does not vary with any instance of the generic, and it is necessary for callers to not call the function with types that do not conform to the type bound, so how can the JVM enforce the type bound if it is erased? Well one link says the type bound is retained in metadata which compilers are supposed to access. And this explains why using type bounds doesn't enable overloading. It also means that JVM is a wide open security hole since type bounded methods can be called without type bounds (yikes!), so excuse me for assuming the JVM designers wouldn't do such an insecure thing.
At the time I wrote this, I didn't understand that stackoverflow was a system of rating people by quality of answers like some competition over reputation. I thought it was a place to share information. At the time I wrote this, I was comparing reified and non-reified from a conceptual level (comparing many different languages), and so in my mind it didn't make any sense to erase the type bound.