问题描述
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,A](sendMessage(response).map(_ => response).runToFuture
}yield response).value
到目前为止,所有这些都很好。但是现在,我想从sendMessage中获取布尔值,然后仅当sendMessage返回true时,才想调用anotherMethod。
我知道他们是不同的单子。请让我知道一种更简洁的方式,如何添加所有三个电话以进行理解。感谢帮助
解决方法
不幸的是,EitherT和Task是不同的monad,而monad没有组成,因此您不能将它们直接用于同一理解。
您可以做的是将Task放入EitherT,但在这种情况下,EitherT的类型参数F必须为Task,在您的情况下为Future。
所以您必须做两件事:
- 将任务转化为未来
- 为EitherT带来未来
假设您的另一种方法如下:
def anotherMethod(input: Integer): EitherT[Future,Exception,Unit] = EitherT.rightT[Future,Exception](())
因此您的理解力可能是这样的:
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,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
要在编辑后回答您的问题,您可以使用whenA
有条件地在理解中使用效果:
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
}