Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with Option and Either types - idiomatic conversions?

Tags:

idioms

scala

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?

like image 422
Karl Knechtel Avatar asked Sep 21 '11 21:09

Karl Knechtel


2 Answers

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.

like image 111
axel22 Avatar answered Sep 28 '22 06:09

axel22


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).

like image 40
Vlad Patryshev Avatar answered Sep 28 '22 07:09

Vlad Patryshev