Consider the following simple code for creating type types. In this first section, I can create an Identity class for any type.
scala> trait Equals[A] { def equal(a1 : A, a2 : A) : Boolean } defined trait Equals scala> sealed trait Identity[A] { | def value : A | def ===(b : A)(implicit e : Equals[A]) = e.equal(value, b) | } defined trait Identity scala> implicit def ToIdentity[A](a : A) = new Identity[A] { val value = a } ToIdentity: [A](a: A)java.lang.Object with Identity[A]
So, if I create a class of type Equals[Int] , now I have to use my types equal to:
scala> implicit val EqualsInt = new Equals[Int] { def equal(i1 : Int, i2 : Int) = i1 == i2 } EqualsInt: java.lang.Object with Equals[Int] = $anon$1@7e199049 scala> 1 === 2 res1: Boolean = false scala> 1 === 1 res2: Boolean = true scala> 1 === 1D <console>:10: error: type mismatch; found : Double(1.0) required: Int 1 === 1D ^
Ok, so far so good. What happens if I create Equals[Any] ?
scala> implicit val EqualsAny = new Equals[Any] { def equal(a1 : Any, a2 : Any) = a1 == a2 } EqualsAny: java.lang.Object with Equals[Any] = $anon$1@141d19 scala> 1 === 1D <console>:11: error: type mismatch; found : Double(1.0) required: Int 1 === 1D ^
But if I tell the compiler that my type is Any , not Int ...
scala> (1 : Any) === 1D res6: Boolean = true
So my question is: βWhy doesn't the compiler consider all types that 1 logically has?β
That is, I realized that a link of type Int logically has types Int , AnyVal and Any . Anyway, I researched a bit more, suggesting that the problem is related to covariance. I changed my Identity definition:
scala> sealed trait Identity[+A] { | def value : A | def ===[B >: A : Equals](b : B) = implicitly[Equals[B]].equal(value, b) | } defined trait Identity
This time I got an error:
scala> 1 === 1D <console>:10: error: could not find implicit value for evidence parameter of type Equals[AnyVal] 1 === 1D ^
So, if I create Equals[AnyVal] , then this also works:
scala> implicit val EqualsAnyVal = new Equals[AnyVal] { def equal(a1 : AnyVal, a2 : AnyVal) = a1 == a2 } EqualsAnyVal: java.lang.Object with Equals[AnyVal] = $anon$1@67ce08c7 scala> 1 === 1D res4: Boolean = true
So, here I am assuming that the problem is related to Equals non- Equals . So I try again (but not creating Equals[AnyVal] ):
scala> trait Equals[-A] { def equal(a1 : A, a2 : A) : Boolean } defined trait Equals scala> 1 === 1D res3: Boolean = true
So, I can see what typer does here. But my question looks like this:: why doesnβt the tester ask the question (for my first example):
- 1 is
Int ; with implicits in scope, I can create an Identity[Int] and then use the === method. But this does not work, because the argument is not Int . Try to use alternative types for 1. - 1 is
AnyVal ; With implicits in scope, I can create Identity[AnyVal] and then use === . But this does not work, because although the argument is AnyVal , there is no implicit Equals[AnyVal] . Try to use alternative types for 1. - 1 is
Any ; With implicits in scope, I can create Identity[Any] and then use === . This works because both arguments are Any , and there are Equals[Any] in the scope.
Why does output type only consider the strictest type 1 (i.e. int)?