How to transform disjunction of Future to Future of disjunction

a 夏天 提交于 2019-12-04 15:07:33

Just as sequence allows you to turn a F[G[A]] into a G[F[A]] when F has a Traverse instance and G is applicative, bisequence lets you turn a F[G[A], G[B]] into a G[F[A, B]] if F has a Bitraverse instance (and G is applicative).

Cats has provided a Bitraverse implementation for at least a couple of versions (I'm using 0.6.0-M2 here), so you can just write this:

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 is a little like Scalaz's Zip or Cozip (mentioned in the other answer), but it's more generic in that instances can be defined for any type constructor with two type arguments (assuming it has the appropriate semantics), not just tuples or disjunction.

Scalaz has Functor.counzip, but there is no counzip in scalaz.syntax.functor so we need to call it on Functor[Future] directly :

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 also has a Cozip type class which gives you the inverse : F[A \/ B] => F[A] \/ F[B].

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!