I wanted to add an answer to abort-early-in-a-fold for ZIO.
So I took the solution with cats: cats solution
def sumEvenNumbers(nums: Stream[Int]): Option[Long] = {
import cats.implicits._
nums.foldM(0L) {
case (acc, c) if c % 2 == 0 => Some(acc + c)
case _ => None
}
}
How can this be achieved with ZIO?
The closest I got:
new DefaultRuntime {}
.unsafeRun(sumEvenNumbers(List(2,4,6,3,5,6)))
def sumEvenNumbers(nums: Iterable[Int]): ZIO[Any, Nothing, Int] = {
stream.Stream.fromIterable(nums)
.run(Sink.fold(0)(s => s % 2 == 0) { (a: Int, b: Int) => (a + b, Chunk.empty)
})
}
But that gives me: 15
instead of 12
. So it seems to short circuit but it takes a number too many. And it is an Int
not Option[Int]
.
A solution without zio.stream.Stream
:
def sumEvenNumbers(as: Iterable[Int]): UIO[Option[Int]] =
ZIO
.foldLeft(as)(0)((s, a) => if (a % 2 == 0) ZIO.succeed(s + a) else ZIO.fail(s))
.option
.foldLeft
- as soon as a number is not even - the fold fails..option
to merge the Error channel to the Success channel to an Option
.