我有下面的代码
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
到目前为止,一切都很好。但现在,我想从sendMessage中获得布尔值,然后只有当sendMessage返回true时,我才想调用另一个方法。
我知道它们是不同的单子。请让我知道一个更干净的方法,我可以添加所有三个调用来进行理解。感谢的帮助
不幸的是,EitherT和Task是不同的单体,并且单体不组成,因此您不能直接在同一个中使用它们进行理解。
你可以做的是将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, 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
要在编辑后回答您的问题,您可以使用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
}