如何在Scala中链接Future[\/[A,B]]? [英] How to chain Future[\/[A,B]] in scala?

查看:49
本文介绍了如何在Scala中链接Future[\/[A,B]]?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何对 Future[\/[String,Int]]

这是一个不编译的起点.

Here is a starting point, which doesn't compile.

import scala.concurrent.{ExecutionContext,future,Future}
import scalaz._
import Scalaz._
import ExecutionContext.Implicits.global

def calculateStuff(i:Int):Future[\/[String,Int]] = future{\/-(i)}

for {
   v1Either <- calculateStuff(1)
   v1Int <- v1Either
   v2Either < calculateStuff(v1Int)
   v2Int <- v2Either
   v3Either <- calculateStuff(v2Int)
   v3Int <- v3Either
} yield {
   v1Int + v2Int + v3Int
}

注意:calculateStuff 只是一个例子,实际上会有不同的函数,每个函数都取决于前面的结果.

Note: calculateStuff is just an example, there will be actually different functions, each depending on the result of the previous.

推荐答案

我首先要注意的是,我假设您有一个很好的理由来实现自己的错误处理(通过 \/)而不是使用 Future

I should first note that I'm assuming that you have a good reason for implementing your own error handling (via \/) instead of using the functionality built into Future

如果是这种情况,那么正如您的标签所暗示的那样,这种问题正是 monad 转换器的用途——只需将您的计算包装在 EitherT 中:

If this is the case, then as your tag suggests, this kind of problem is exactly what monad transformers are for—just wrap your calculation in an EitherT:

import scalaz._, Scalaz._, contrib.std._
import scala.concurrent.{ ExecutionContext, future, Future }
import ExecutionContext.Implicits.global

def calculateStuff(i: Int): EitherT[Future, String, Int] =
  EitherT(future(\/-(i)))

val computation = for {
   v1Int <- calculateStuff(1)
   v2Int <- calculateStuff(v1Int + 1)
   v3Int <- calculateStuff(v2Int + 2)
} yield v1Int + v2Int + v3Int

请注意,我正在将 Monad 实例用于 Typelevel 的 Futurescalaz-contrib 库.

Note that I'm using the Monad instance for Future from Typelevel's scalaz-contrib library.

现在 computation.run 会给你一个 Future[String \/Int].

Now computation.run will give you a Future[String \/ Int].

如果你需要在计算中注入一个纯值,你可以只使用 point 和一个 lambda 类型:

If you need to inject a pure value into the computation, you can just use point and a type lambda:

v4Int <- 1.point[({ type L[x] = EitherT[Future, String, x] })#L]

你也可以定义你自己的类型别名,让它看起来更好看.

You could also define your own type alias to make this look a little nicer.

如果你想在 for-comprehension 中使用一个 \/ 值,你可以将它指向 Future 并包装整个EitherT 中的东西:

If you want to use a \/ value in the for-comprehension, you can just point it into Future and wrap the whole thing in EitherT:

v5Int <- EitherT(1.right[String].point[Future])

也可以使用(有点令人困惑的名称)liftM 将一个普通的 Future 提升到转换后的 monad 中:

It's also possible to lift a plain old Future into the transformed monad with the (somewhat confusingly named) liftM:

v6Int <- future(1).liftM[({ type T[m[+_], a] = EitherT[m, String, a] })#T]

在这种情况下,您几乎肯定需要一个类型别名——该行主要是噪音.

In this case you almost certainly want a type alias—that line's mostly noise.

这篇关于如何在Scala中链接Future[\/[A,B]]?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆