我如何for
对类型的数据进行理解Future[\/[String,Int]]
这是一个起点,尚未编译。
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
这只是一个示例,实际上会有不同的功能,每个功能都取决于前一个的结果。
首先,我假设您有充分的理由实施自己的错误处理(通过\/
),而不是使用内置的功能Future
如果是这种情况,那么正如您的标签所暗示的那样,此类问题正是monad转换器的目的-只需将您的计算结果包装在中即可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
实例Future
从Typelevel的scalaz-的contrib库。
现在computation.run
会给你一个Future[String \/ Int]
。
如果您需要向计算中注入纯值,则可以使用point
和lambda类型:
v4Int <- 1.point[({ type L[x] = EitherT[Future, String, x] })#L]
您也可以定义自己的类型别名,以使外观更好看。
如果要\/
在for
-comprehension中使用值,则可以Future
将其指向并包装整个内容EitherT
:
v5Int <- EitherT(1.right[String].point[Future])
也可以Future
使用(有点易混淆的名字)将一个普通的旧的东西提升到转换后的monad中liftM
:
v6Int <- future(1).liftM[({ type T[m[+_], a] = EitherT[m, String, a] })#T]
在这种情况下,您几乎可以肯定要使用类型别名-该行主要是噪音。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句