Reputation: 3863
I am struggling in how to compose a sequence of asynchronous processes in a nice monadic way. Each step of the process could fail so it is retrieving a Future[Either[String, T]]
.
def firstStep(input: Int): Future[Either[String, Long]] = ???
def secondStep(input: Long): Future[Either[String, String]] = ???
def thirdStep(input: String): Future[Either[String, Double]] = ???
Given these functions I would like to compose them like this
def process(input: Int): Future[Either[String Double]] = {
for{
res1 <- firstStep(input)
res2 <- secondStep(res1)
res3 <- thirdStep(res2)
} yield res3
}
But this doesn't work because each partial result is an Either[String, T]
,and what I need is the T
itself (or just stop the execution and return the Left
if that's the case).
How can I compose this functions in a nice monadic way (using for-comprehensions)?
Upvotes: 5
Views: 1796
Reputation: 149538
An EitherT
monad transformer can help, either (pun intended) from cats or scalaz:
import cats._
import cats.implicits._
import cats.EitherT
def process(input: Int): Future[Either[String, Double]] = {
val res = for {
res1 <- EitherT(firstStep(input))
res2 <- EitherT(secondStep(res1))
res3 <- EitherT(thirdStep(res2))
} yield res3
res.value
}
Upvotes: 7