我有一个方法的结果:
val res: Future[Int] Xor Future[String] = getResult(x)
并想对其进行改造并将其用作Future[Int Xor String]
我无法从牧猫博客中推断出我的用例,并且不确定 monad 转换器是否是正确的工具,也许是某种形式的traverse
?
Xor
from cat 代表任何分离。Scalaz\/
或 stdlibEither
也可以(尽管我更喜欢有偏见的析取)。
谢谢
我有一个方法的结果:
val res: Future[Int] Xor Future[String] = getResult(x)
并想对其进行改造并将其用作Future[Int Xor String]
我无法从牧猫博客中推断出我的用例,并且不确定 monad 转换器是否是正确的工具,也许是某种形式的traverse
?
Xor
from cat 代表任何分离。Scalaz\/
或 stdlibEither
也可以(尽管我更喜欢有偏见的析取)。
谢谢
就像sequence
允许你将 aF[G[A]]
变成一个G[F[A]]
whenF
有一个Traverse
实例并且G
是可应用的一样,bisequence
让你将 aF[G[A], G[B]]
变成 a G[F[A, B]]
ifF
有一个Bitraverse
实例(并且G
是可应用的)。
Cats 提供了至少几个版本Bitraverse
的实现(我在这里使用 0.6.0-M2),所以你可以这样写:
import cats.data.Xor, cats.std.future._, cats.syntax.bitraverse._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def flip[A, B](x: Xor[Future[A], Future[B]]): Future[Xor[A, B]] = x.bisequence
Bitraverse
有点像 Scalaz 的Zip
or Cozip
(在另一个答案中提到),但它更通用,因为可以为具有两个类型参数的任何类型构造函数定义实例(假设它具有适当的语义),而不仅仅是元组或析取。
Scalaz 有Functor.counzip
,但没有counzip
inscalaz.syntax.functor
所以我们需要Functor[Future]
直接调用它:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz.std.scalaFuture._
import scalaz.{\/, Functor}
val disj: Future[Int] \/ Future[String] = \/.right(Future.successful("foo"))
Functor[Future].counzip(disj)
// Future[Int \/ String] : Success(\/-(foo))
Scalaz 也有一个Cozip
类型类,它为您提供逆:F[A \/ B] => F[A] \/ F[B]
。