# Scala Either question

``````   val left42 : Left[Double, Nothing]   = Left(42.0)
val left23: Left[Double, Int]  = Left(23.0)
val result = for {
a <- left23
b <- left42
} yield(a + b)``````

## Why the above code gives the following compilation error ?

Error:(37, 19) 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(a + b)

That code may not mean what you intend. `Either` is â€śright-biasedâ€ť, where the right-hand side is the â€śrealâ€ť one that propagates down through `for`; the left-hand side is typically used for error conditions. So

``````b <- left42
``````

means `b` has type `Nothing` (since that is the right-hand side of `left42`), and `+` doesnâ€™t exist on `Nothing`.

I suspect you want your lefts and rights to be reversed, but Iâ€™m not sure what the intent of the above code isâ€¦

If â€śleft42â€ť is treated as Nothing because Either is right biased as you said then how come the following works.

``````   val left42 : Left[Double, Int]   = Left(42.0)
val left23: Left[Double, Int]  = Left(23.0)
val result = for {
a <- left23
b <- left42
} yield(a + b)``````

result: scala.util.Either[Double,Int] = Left(23.0)

All I changed was the type and it has Left[Double,Int] now for left42

Because `Int` has a `+` operator, so this version of the code is legal. Your first version fails only because you explicitly typed it as `Nothing`.

Note that your `+` only applies to the right-hand side, and your example here shows that: it gets to:

``````a <- left23
``````

and since the value passed in is a `Left`, it skips the line:

``````b <- left42
``````

and returns the value of `left23`.

But the code still needs to compile, and your original example up top was trying to add an `Int` and a `Nothing`, which doesnâ€™t make any sense, so the compiler rejects it.

Basically, the left-hand side of an `Either` is not usually set â€“ when it does get set, that generally indicates an error, so all further processing gets skipped and it just returns the first `Left` it encounters. The `for` comprehension normally expects you to be composing `Right`s instead. The type of `a` and `b` will always be the type of the right-hand side of the `Either`. So the `yield` has to make sense with those types.

NB: all of the above applies only to Scala 2.12 and later. In 2.11 and before, Either was un-biased, and you couldnâ€™t simply use it like this in a `for` comprehension â€“ you had to explicitly say whether you wanted to use the left or right. But at this point, the right-hand side should always be used for the real data, and the left-hand side for the â€śshort-circuitingâ€ť data, usually an error code of some sort.

1 Like

Thanks. I understand that now. Now my question is that the computation in the yield part (i.e a + b) is not going to have any impact at all in the for comprehension because we have both â€śLeftâ€ť in the for comprehension. It does not matter and whatever the computation in the yield part the result is going to be just Left(23.0) right ? Then why the heck the compiler spits the error ? Yeah, I completely understand it takes the right values for computation. If there are no any Right values at all as in our case above what is the point in the computation ? I know nobody is going to do this way in real life. But my argument is that if the compiler sees that all are Left (or) at least one is Left in the for comprehension then it should ignore the computation in the yield part because the computation is not going to happen and not going to have any impact in the final result.
Please correct me if I am wrong.

Well, youâ€™re wrong. If compiler sees following code:

``````if (2 + 2 == 5) {
here is some garbage that can't compile
}
``````

Then it signals compilation error even if itâ€™s obvious that the code inside the `if` would never have the chance to execute. Same goes for everything else, i.e. all the code must be syntactically correct and have correct types.

1 Like

Well, the code is in error. Youâ€™re expecting way too much brilliance from the compiler (discussed below), but it is Just Plain Broken â€“ that `yield` canâ€™t possibly work in your first example, so flagging it as an error makes sense. The error message isnâ€™t quite as clear as you might wish, but itâ€™s 100% correct.

Iâ€™m not an expert in the compiler, but hereâ€™s the way I believe this is playing out:

First, keep in mind that `for` comprehensions know nothing whatsoever about `Left` per se; indeed, `for` doesnâ€™t really exist. `for` is just a bit of syntax sugar that gets translated into function calls, and will work for any type that has `map` and `flatMap` defined. `Left` does define those, even though they simply fall through, so the compiler uses them to build the actual code that gets compiled:

``````   val result = left23.flatMap { a: Int =>
left42.map { b: Nothing =>
a + b
}
}
``````

Thatâ€™s essentially the code that is actually being compiled â€“ the `for` gets rewritten to that.

The compiler knows nothing whatsoever about the fact that `Left` falls through â€“ itâ€™s just another type that has `map` and `flatMap`, like hundreds of others. Keep in mind, `Left` is just a type. It isnâ€™t defined by the compiler, itâ€™s defined in the standard library, and the compiler intentionally avoids knowing too much about the standard library. (People complain enough about the speed of the compiler â€“ it would be vastly worse if it tried to be clever about special cases like this.)

What the compiler does know, though, is that `a + b` is illegal because you canâ€™t add `Nothing` to `Int` â€“ the `+` operator isnâ€™t defined for that. So thatâ€™s the error you actually get.

2 Likes

Agree. Thank You.