I have below code
def processInfoAndReturnResponse(input: Input]): EitherT[Future, CustomException, A] = ???
def sendMessage(message: A): monix.eval.Task[Boolean] = ???
def anotherMethod(message: Input): Future[Either[CustomException, Unit]]= ???
def integrate(): Future[Either[GoogleException, A]] = {
(for {
response <- processInfoAndModelResponse(input)
_ <- EitherT.liftF[Future, CustomException, A](sendMessage(response).map(_ => response).runToFuture
}yield response).value
so far all this is good. But now, I want to get boolean from sendMessage and then only if sendMessage returns true, I want to call anotherMethod.
I understand they are different monads. Please let me know a cleaner way how I can add all three calls in for comprehension. Appreciate help
Unfortunately, EitherT and Task are different monads and monads doesn't compose so you can't use them directly in the same for comprehension.
What you could do is lifting Task into EitherT but in this case type parameter F of EitherT would have to be Task and in your case it's Future.
So you have to do 2 things:
Let's say your another method looks like this:
def anotherMethod(input: Integer): EitherT[Future, Exception, Unit] = EitherT.rightT[Future, Exception](())
So your for-comprehension could look like this:
import cats.implicits._
import scala.concurrent.ExecutionContext.Implicits._
val prog = for {
//you need to use leftWiden adjust left of either to common type
response <- processInfoAndReturnResponse(inp).leftWiden[Exception]
//running task to Future and then lifting to EitherT
i <- EitherT.liftF[Future, Exception, Integer](sendMessage(response).runToFuture)
_ <- anotherMethod(i)
} yield ()
//prog is of type EitherT so we have to unwrap it to regular Future with rethrowT
val future: Future[Unit] = prog.rethrowT
To answer your question after edit, you can use whenA
to conditionaly use effect in for-comprehension:
def integrate(): Future[Either[GoogleException, A]] ={
(for {
response <- processInfoAndModelResponse(input)
sendStatus <- EitherT.liftF[Future, CustomException, Boolean](sendMessage(response).runToFuture)
finalresult <- anotherMethod(input).whenA(sendStatus)
} yield finalresult).value
}