I found "ambiguous reference to overloaded definition" while trying to practice scala interview question.
I was trying to find the outcome of following code block which results in compilation error :
Code :
for {
v1 <- Left[Int,Int](1)
v2 <- Right(2)
v3 <- Right(3)
v4 <- Left(4)
} yield v1 + v2 + v3 + v4
Error :
<pastie>:17: error: ambiguous reference to overloaded definition,
both method + in class Int of type (x: Char)Int
and method + in class Int of type (x: Byte)Int
match argument types (Nothing)
} yield v1 + v2 + v3 + v4
^
Why Scala compiler gives ambiguous reference error when we specified type only on v1 field but not on v4 ?
I also tried following version with different parameter type in v1 and v4 and it worked !
for {
v1 <- Left[String,Int]("1")
v2 <- Right(2)
v3 <- Right(3)
v4 <- Left[Int, Int](4)
} yield v1 + v2 + v3 + v4
And the output is :
res20: scala.util.Either[Any,Int] = Left(1)
I tried with one more version which also resulted into error :
for {
v1 <- Left(1)
v2 <- Right(2)
v3 <- Right(3)
v4 <- Left(4)
} yield v1 + v2 + v3 + v4
output :
<console>:17: error: value + is not a member of Nothing
} yield v1 + v2 + v3 + v4
How exactly the for comprehension works here with Left
and Right
? Why the first and last case are not working in my example ?
It's because there's no common inferred types and you didn't specify the types for all the Either
.
So
scala> for (v1 <- Right(2)) yield v1
res13: scala.util.Either[Nothing,Int] = Right(2)
Solution is to give them common types
for {
v1 <- Left[Int,Int](1)
v2 <- Right[Int,Int](2)
v3 <- Right[Int,Int](3)
v4 <- Left[Int,Int](4)
} yield v1 + v2 + v3 + v4
Which gives Left(1)
. This result makes sense due to Either
being right-biased and for comprehension serving as a flatMap
.
According to the documentation:
"Either is right-biased, which means that Right is assumed to be the default case to operate on. If it is Left, operations like map, flatMap, ... return the Left value unchanged"
https://www.scala-lang.org/api/2.12.0/scala/util/Either.html