[英]Different monads in for comprehension
我有以下代碼
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 時,我才想調用 anotherMethod。
我知道它們是不同的單子。 請讓我知道一種更簡潔的方式,我可以如何添加所有三個調用以進行理解。 感謝幫助
不幸的是,EitherT 和 Task 是不同的 monads,並且 monads 不能組合,所以你不能直接使用它們來理解。
您可以做的是將 Task 提升到 ThatiT 中,但在這種情況下,EitherT 的類型參數 F 必須是 Task,而在您的情況下,它是 Future。
所以你必須做兩件事:
假設您的另一種方法如下所示:
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
在 for-comprehension 中有條件地使用 effect:
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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.