My computation that can fail is halve()
below. It returns Left(errorMessage)
to indicate failure and Right(value)
to indicate the successful halving of a number.
def halve(n: Int): Either[String, Int] =
if (n % 2 == 0) {
Right(n / 2)
} else {
Left("cannot halve odd number")
}
I'd like to apply the halve
function to a list of Int
s such that as soon as the first call to halve
fails (e.g. when called with an odd number), the halveAll
function immediately stops iterating over the numbers in ns
and returns Left(errorMessage)
.
Here is one way to achieve this:
def halveAll(ns: List[Int]): Either[String, List[Int]] =
try {
Right(
for {
n <- ns
Right(halved) = halve(n)
} yield n
)
} catch {
case ex: MatchError =>
Left("cannot match an odd number")
}
I would prefer an approach that does not use exceptions. Is there an idiomatic way of achieving this? I'd prefer the approach to use only functionality in the Scala 2.x standard library. If Cats or scalaz has an elegant solution, I'd be interested in hearing about it though.
Thank you!
Example usage of the halveAll
function:
val allEven = List(2, 4, 6, 8)
val evenAndOdd = List(2, 4, 6, 7, 8)
println(halveAll(allEven))
println(halveAll(evenAndOdd))