I'm probably missing something that's right in the documentation, but I can't really make much sense of it - I've been teaching myself Scala mostly by trial and error.
Given a function f: A => C
, what is the idiomatic way to perform the following conversions?
Either[A, B] -> Either[C, B]
Either[B, A] -> Either[B, C]
(If I have two such functions and want to convert both sides, can I do it all at once or should I apply the idiom twice sequentially?)
Option[A] -> Option[C]
(I have a feeling that this is supposed to use for (...) yield
somehow; I'm probably just blanking on it, and will feel silly when I see an answer)
And what exactly is a "projection" of an Either
, anyway?
You do either a:
either.left.map(f)
or a:
either.right.map(f)
You can also use a for-comprehension: for (x <- either.left) yield f(x)
Here's a more concrete example of doing a map
on an Either[Boolean, Int]
:
scala> val either: Either[Boolean, Int] = Right(5)
either: Either[Boolean, Int] = Right(5)
scala> val e2 = either.right.map(_ > 0)
either: Either[Boolean, Boolean] = Right(true)
scala> e2.left.map(!_)
either: Either[Boolean, Boolean] = Right(true)
EDIT:
How does it work? Say you have an Either[A, B]
. Calling left
or right
creates a LeftProjection
or a RightProjection
object that is a wrapper that holds the Either[A, B]
object.
For the left
wrapper, a subsequent map
with a function f: A => C
is applied to transform the Either[A, B]
to Either[C, B]
. It does so by using pattern matching under the hood to check if Either
is actually a Left
. If it is, it creates a new Left[C, B]
. If not, it just changes creates a new Right[C, B]
with the same underlying value.
And vice versa for the right
wrapper. Effectively, saying either.right.map(f)
means - if the either (Either[A, B]
) object holds a Right
value, map it. Otherwise, leave it as is, but change the type B
of the either object as if you've mapped it.
So technically, these projections are mere wrappers. Semantically, they are a way of saying that you are doing something that assumes that the value stored in the Either
object is either Left
or Right
. If this assumption is wrong, the mapping does nothing, but the type parameters are changed accordingly.
Given f: A=>B
and xOpt: Option[A]
, xOpt map f
produces the Option[B]
you need.
Given f: A=>B
and xOrY: Either[A, C]
, xOrY.left.map(f)
produces the Either
you are looking for, mapping just the first component; similarly you can deal with RightProjection
of Either
.
If you have two functions, you can define mapping for both components, xOrY.fold(f, g)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With