Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
414 views
in Technique[技术] by (71.8m points)

scalaz - How to chain Future[/[A,B]] in scala?

How I can do a for comprehension with the data of type 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
}

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

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

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

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

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.

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])

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...