I've got a Future[Either[A, B]]
and a function providing a Future[C]
from a B
.
I need to transform the Future[Either[A, B]]
to Future[Either[A, C]]
.
Is there a direct way to get the Future[Either[A, C]]
and not a Future[Either[A, Future[C]]]
?
I'm thinking about something like:
val eventuallyInitialValue: Future[Either[A, B]] = ???
val result: Future[Either[A, C]] = for {
e: Either[A, B] <- initialValue
c: C <- service.getValue(e.right)
} yield e.right.map(_ => c)
It's just pseudo-code since service.getValue(e.right)
does not compile. What would be the correct way of doing it?
This is what I came up with:
type B = Int
type A = String
type C = Long
val eitherF: Future[Either[A, B]] = ???
def f(b: B): Future[C] = ???
val mapped: Future[Either[A, C]] = eitherF.flatMap {
case Left(a) =>
Future.successful(Left(a))
case Right(b) =>
f(b).map(Right(_))
}
Basically you can flatMap
the future and then if it's a left just return the success, if it's a right you can apply the future and map a Right
to it.
Here is scalaz solution. Note that it uses scalaz version of either.
class A
class B
class C
val initial: Future[A \/ B] = (new B).right.point[Future]
val f: B => Future[C] = _ => (new C).point[Future]
val result: Future[A \/ C] = (for {
e <- EitherT(initial)
res <- EitherT(f(e).map(_.right))
} yield res).run
It is basically the same what @Ende Neu did but the matching and rewrapping is hidden in monad transformer.
You can do this by lifting the B => Future[C]
function into an Either[E, B] => Future[Either[E, C]]
function and then you can flatMap
on the original future.
eventuallyInitialValue.flatMap {
case Left(e) => Future.successful(Left(e))
case Right(r) => bToFC(r).map(Right.apply _)
}
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