Convert Option to Either in Scala
No, if you do it this way, you can't leave out the type.
The type of Left("No number")
is inferred to be Either[String, Nothing]
. From just Left("No number")
the compiler can't know that you want the second type of the Either
to be Int
, and type inference doesn't go so far that the compiler will look at the whole method and decide it should be Either[String, Int]
.
You could do this in a number of different ways. For example with pattern matching:
def foo(ox: Option[Int]): Either[String, Int] = ox match {
case Some(x) => Right(x)
case None => Left("No number")
}
Or with an if
expression:
def foo(ox: Option[Int]): Either[String, Int] =
if (ox.isDefined) Right(ox.get) else Left("No number")
Or with Either.cond
:
def foo(ox: Option[Int]): Either[String, Int] =
Either.cond(ox.isDefined, ox.get, "No number")
I am not sure which version of Scala you were using at the time. Currently, with Scala 2.12.6 there's no compilation problems with your code like this:
def foo(ox: Option[Int]): Either[String, Int] =
ox.toRight("No number")
One other point I'd like to make is that folding (while it's my preferred method of collapsing just about anything that has a fold method on it) quite often requires help with type parameters. There's two ways the compiler can type check an expression, either it can infer the type parameters or it can simply find them explicitly defined.
In your example, if you're trying to fold an option like so:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold(Left("No number") : Either[String, Int])(x => Right(x))
You're explicitly providing type information about the first argument, which in turn can be then used to infer the type parameter of fold
. You're aiding the type inference mechanism.
On the other hand, you could simply just explicitly provide the type parameter for fold
like so:
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold[Either[String, Int]](Left("No number"))(x => Right(x))
Now your actual (value-level) arguments are not littered with superfluous type information, and there's no type inference going on when the compiler looks at it, it can tell right away what fold
's type parameter is, as it's been explicitly provided. Use the square brackets to specify the type parameter explicitly.
One more point, regarding x => Right(x)
here you're practically creating a new function literal that does nothing other than pass x into the apply
method of the Right case class's companion object. You already have a function of the appropriate shape available. It takes x
and returns a Right(x)
. It is the apply
method. You can refer to it (pass it) directly.
def foo(ox: Option[Int]): Either[String, Int] =
ox.fold[Either[String, Int]](Left("No number"))(Right.apply)