[英]Cats get value from the monad stack
我有一個monad堆棧,用於響應使用cats monads變壓器實現的組件的響應:
type FutureEither[A] = EitherT[Future, Error, A]
type FutureEitherOption[A] = OptionT[FutureEither, A]
結果是有效的:
Future[Either[Error, Option[A]]]
如何以適當的方式從此堆棧中獲取值或錯誤? 如何合並以適當方式並行執行的多個調用的結果? 例如在這種情況下:
def fooServiceCall: FutureEitherOption[Foo]
def barServiceCall(f: Option[Foo]): FutureEitherOption[Bar]
for {
r1 <- fooServiceCall
r2 <- barServiceCall(r1)
} yield r2
您的第二個方法barServiceCall
在其簽名中告訴它可以直接處理Option[Foo]
,而不是依賴monad轉換器堆棧在某些時候失敗並顯示None
。 因此,您必須拆開一層OptionT[EitherT[Future, Error, ?], A]
EitherT[Future, Error, Option[A]]
,然后直接處理EitherT[Future, Error, Option[A]]
:即使您的方法似乎在前者是monad堆棧,這種理解的正確工具是后者。
回想一下,如果o: OptionT[F, A]
,則包裝的o.value
為F[Option[A]]
。
因此,如果僅在OptionT[EitherT[Future, Error, ?], A]
上調用.value
, OptionT[EitherT[Future, Error, ?], A]
獲得所需的EitherT[Future, Error, Option[A]]
。 這是它在代碼中的工作方式:
import scala.concurrent.Future
import scala.util.Either
import cats.instances.future._
import cats.instances.either._
import cats.instances.option._
import cats.data.EitherT
import cats.data.OptionT
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
type Error = String // or whatever...
type Foo = (Int, Int) // whatever...
type Bar = (String, Float) // whatever...
type FutureEither[A] = EitherT[Future, Error, A]
type FutureEitherOption[A] = OptionT[FutureEither, A]
def fooServiceCall: FutureEitherOption[Foo] = ???
def barServiceCall(f: Option[Foo]): FutureEitherOption[Bar] = ???
val resFut: Future[Either[Error, Option[Bar]]] = (for {
r1 <- fooServiceCall.value // : EitherT[Future, Error, Option[Foo]]
r2 <- barServiceCall(r1).value // : EitherT[Future, Error, Option[Bar]]
} yield r2).value
val res: Either[Error, Option[Bar]] = Await.result(resFut, 10.seconds)
現在,結果非常簡單,您可以直接對其進行處理。
另外,如果您不想在此時此地解壓縮結果,可以將其再次包裝到OptionT
並繼續使用FutureEitherOption[Bar]
:
val res2: FutureEitherOption[Bar] =
OptionT(for {
r1 <- fooServiceCall.value
r2 <- barServiceCall(r1).value
} yield r2)
您可以在OptionT[F, A]
上調用.value
以獲得F[Option[A]]
。 只需執行OptionT()
即可完成相反操作。 我相信EitherT
有類似的方法,當您需要訪問內部Option
或Either
時,可以使用它們包裝和拆開這些類。 例如,我認為您可以執行以下操作:
val x: FutureEither[Option[Bar]] = for {
r1 <- fooServiceCall.value
r2 <- barServiceCall(r1).value
} yield r2
val result: FutureEitherOption[Bar] = OptionT(x)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.