Do you build reactive applications using Scala? Then chances are you’ve had to deal with a Future[Monad[T]]
, where Monad
could be Option
, Either
, or something more wonderful like Or
. While these monads do nest as expected, the syntax and code flow can start to get pretty messy (motivating example below).
Enter FutureOr! This utility makes it super-simple to sequence several Future[Or[T]]
calls. It’s also fairly easy to implement, so you could easily clone this and customize for your favorite nested monad combination.
//three service calls which return Future[Or[T]] and depend on the previous call
trait IntService{
def callA: Future[Int Or One[ErrorMessage]]
def callB(int a): Future[Int Or One[ErrorMessage]]
def callC(int b): Future[Int Or One[ErrorMessage]]
}
val service: IntService = ...
//without FutureOr, really ugly! I wouldn't wish this on my worst enemy!
val result: Future[Int Or One[ErrorMessage]] =
service.callA.flatMap{ a =>
a.flatMap{
case Good(goodA) => service.callB(goodA).flatMap { b =>
b.flatMap {
case Good(goodB) => service.callC(goodB)
case Bad(e) => Future.successful(Bad(e))
}
}
case Bad(e) => Future.successful(Bad(e))
}
}
//with FutureOr, so much better!
val result: Future[Int Or One[ErrorMessage]] =
(for {
a <- FutureOr(service.callA)
b <- FutureOr(service.callB(a))
c <- FutureOr(service.callC(b)
} yield c).future