I would like to initialize an Either
to Left
, but this requires specifying the type of the Right
side (or vice versa).
If I don't, then the Right
side is typed to Nothing
by default, and in order to do something such as:
List(5, 42, 7).foldLeft(Left("empty")) {
case (Left(_), i) => Right(i)
case (Right(s), i) => Right(s + i)
}
error: type mismatch;
found : scala.util.Right[Nothing,Int]
required: scala.util.Left[String,Nothing]
I'm obviously forced to verbosely provide the type of both sides of the Either
:
List(5, 42, 7).foldLeft(Left("empty"): Either[String, Int]) {
case (Left(_), i) => Right(i)
case (Right(s), i) => Right(s + i)
}
In a similar way, I can use Option.empty[Int]
to initialize None
as an Option[Int]
, would there be a way to initialize Left("smthg")
as an Either[String, Int]
?
Convention dictates that Left is used for failure and Right is used for success. For example, you could use Either[String, Int] to indicate whether a received input is a String or an Int . Since for comprehensions use map and flatMap , the types of function parameters used in the expression must be inferred.
A common use of Either is as an alternative to Option for dealing with possible missing values. In this usage, scala. None is replaced with a Left which can contain useful information.
Starting Scala 2.13
, Left
comes with a Left#withRight
method which allows upcasting Left[A, Nothing]
to Either[A, B]
:
Left("smthg").withRight[Int]
// Either[String, Int] = Left("smthg")
Left("smthg")
// Left[String, Nothing] = Left("smthg")
Same goes for the Right
side and withLeft
:
Right(42).withLeft[String]
// Either[String, Int] = Right(42)
which gives in your case:
List(5, 42, 7).foldLeft(Left("empty").withRight[Int]) {
case (Left(_), i) => Right(i)
case (Right(s), i) => Right(s + i)
}
// Either[String, Int] = Right(54)
To supplement Xavier's answer, cats also provide utility methods for creating Either
, for example, we can do:
import cats.implicits._
val right = 7.asRight[String] // Either[String, Int]
val left: = "hello cats".asLeft[Int] // Either[String, Int]
It might be useful if in case our project is using scala 2.12 or below.
In case we don't need whole cats library, we can, of course, borrow just extension functions for either:
implicit class EitherIdOps[A](private val obj: A) extends AnyVal {
/** Wrap a value in `Left`. */
def asLeft[B]: Either[A, B] = Left(obj)
/** Wrap a value in `Right`. */
def asRight[B]: Either[B, A] = Right(obj)
}
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