Scala猫,flatMap on cartesian?

时间:2018-02-14 16:08:15

标签: scala scala-cats cartesian

假设:

def doStuff(a: A, b: B): C = ???
val result: M[C] = (ma |@| mb).map(doStuff)

我知道我可以这样做:

flatMap

但我如何flatMap? CartesianBuilder s中没有def doFancyStuff(a: A, b: B): M[C] = ??? val result: M[C] = (ma |@| mb).flatMap(doFancyStuff)

CTrade.OrderModify()

1 个答案:

答案 0 :(得分:1)

我认为主要的问题是,flatMap Future[Either[Error, X]] EitherT[Future, Error, X] - monad堆栈中的flatMap尴尬,因为Future Future 1}}阻碍了,并且编译器没有寻找可以同时处理EitherEitherT组合的monad实例。但是,如果你将期货包裹在(a,b).tupled中,一切都会顺利进行。

对于猫1.0.1

在下文中,Cartesian.product(a, b)对应(a, b).mapN,而(a |@| b).map对应已弃用的A

鉴于类型BCErrorM,以下代码段在cat 1.0.1下编译:

如果你想保留EitherT(你可能应该)的定义,那么你 通过将所有内容包装在value然后,可以避免上述问题 提取import scala.util.Either import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global // required by Monad[Future] import cats.instances.future._ // Monad for `Future` import cats.syntax.apply._ // `tupled` and `mapN` import cats.data.EitherT // EitherT monad transformer type M[X] = Future[Either[Error, X]] val ma: M[A] = ??? val mb: M[B] = ??? def doStuff(a: A, b: B): C = ??? val result1: M[C] = (EitherT(ma), EitherT(mb)).mapN(doStuff).value def doFancyStuff(a: A, b: B): M[C] = ??? val result2: M[C] = (for { ab <- (EitherT(ma), EitherT(mb)).tupled c <- EitherT(doFancyStuff(ab._1, ab._2)) } yield c).value

M

但是,如果这看起来太尴尬了,你可以调整import scala.util.Either import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global // required by Monad[Future] import cats.instances.future._ // Monad for `Future` import cats.syntax.apply._ // `tupled` and `mapN` import cats.data.EitherT // EitherT monad transformer type M[X] = EitherT[Future, Error, X] val ma: M[A] = ??? // either adjust signatures, or wrap result in EitherT(res) val mb: M[B] = ??? def doStuff(a: A, b: B): C = ??? val result1: M[C] = (ma, mb).mapN(doStuff) def doFancyStuff(a: A, b: B): M[C] = ??? val result2: M[C] = (ma, mb).tupled.flatMap{ case (a, b) => doFancyStuff(a, b) } 的定义, 以下变体可能会略短:

(ma, mb).tupled

这是因为M[(A, B)]构建了M,其中flatMap是前面提到的monad堆栈,然后(A, B) => M[C]可以轻松M[C]函数为Cartesian

适用于(ma, mb).tupled(未经测试)

的旧版本

假设Cartesian.product对应于已弃用的(ma, mb).mapN(ma |@| mb).map对应于已弃用的result1,则result2val result1: M[C] = (ma |@| mb).map(doStuff) val result2: M[C] = Cartesian[M].product(ma, mb).flatMap{ case (a, b) => doFancyStuff(a, b) } 的两个定义相对应在上面的代码片段中,1.0.1转换为:

Cartesian[M].product(ma, mb)

同样,这只是因为M[(A, B)]M[A]M[B]构建M[X],其中EitherT[Future, Error, X]定义为Future[Either[Error, X]]。如果它被定义为flatMap,则会Future上调用doFancyStuff,而不是Either[Error, (A, B)] => Future[Either[Error, C]],我们必须传递{{1}}之类的内容,这可能不是你想要的。