I wonder if anyone could explain the inferencing rule in this particular case below, and most importantly it's rational/implication ?
case class E[A, B](a: A) // class E
E(2) // E[Int,Nothing] = E(2)
Note that I could have wrote E[Int](2)
. What matter to me is why is the second parameter type inferred to be Nothing
(i.e. Bottom type) instead of let say Any
for instance ? Why is that and What's the rational/Implication ?
Just to give some context, this is related to the definition of Either and how it works for Left and Right. Both are defined according to the pattern
final case class X[+A, +B](value: A) extends Either[A, B]
Where you instantiate it let say as Right[Int](2)
and the type inferred is Right[Nothing, Int]
and by extension Either[Nothing, Int]
EDIT1
There is consistency here, but i still can figure out the rational. Below is the same definition with a contra-variant paramete:
case class E[A, -B](a: A)// class E
E(2) // E[Int, Any] = E(2)
Hence we do have the same thing the other way around when it is contra-variant, and that make the all behavior or inference rule, coherent. However the rational for this i am not sure ....
Why not the opposite rule i.e. infer Any
when Co-Variant/Invariant and Nothing
when Contra-Variant ?
EDIT2
In the light of @slouc Answer, which make good sense, i'm left with still understanding what and why the compiler is doing what it is doing. The example below illustrate my confusion
val myleft = Left("Error") // Left[String,Nothing] = Left(Error)
myleft map { (e:Int) => e * 4} // Either[String,Int] = Left(Error)
- First the compiler fix the type to something that "for sure work" to reuse the conclusion of @slouc (albeit make more sense in the context of a Function)
Left[String,Nothing]
- Next the compile infer
myleft
to be of type Either[String,Int]
given map definition def map[B](f: A => B): Either[E, B]
, (e:Int) => e * 4
can only be supplied if myleft
is actually Left[String,Int]
or Either[String,Int]
So in other words, my question is, what is the point of fixing the type to Nothing
if it is to change it later.
Indeed the following does not compile
val aleft: Left[String, Nothing] = Left[String, Int]("Error")
type mismatch;
found : scala.util.Left[String,Int]
required: Left[String,Nothing]
val aleft: Left[String, Nothing] = Left[String, Int]("Error")
So why would I infer to a type, that normally would block me to do anything else over variable of that type (but for sure works in term of inference), to ultimately change that type, so i can do something with a variable of that inferred type.
EDIT3
Edit2 is a bit misunderstanding and everything is clarified in @slouc answer and comments.