如何不同类型的到一个单一的未来的期货相结合,而不使用ZIP()(How to combine Fut

2019-07-30 01:53发布

我想创建类型的未来Future[(Class1,Class2,Class3)]从下面的代码。 但是我发现这样做的唯一方法是通过使用拉链()。 我找到解决方案丑,妥善不是最佳的。 有谁能够开导我。

val v = for (
    a <- {
        val f0:Future[Class1] = process1
        val f1:Future[Class2] = process2
        val f2:Future[Class3] = process3
        f0.zip(f1).zip(f2).map(x => (x._1._1,x._1._2,x._2))
    } yield a  // Future[(Class1,Class2,Class3)]

我还试图使用Future.sequence(List(f0, f1, f2))但是这不会作为新的未来工作将具有类型Future[List[U]]其中U是的LUB Class1/2/3而我希望有一个3元组保留原始类型

Answer 1:

val result: Future[(Class1, Class2, Class3)] = {
  val f1 = process1
  val f2 = process2
  val f3 = process3
  for { v1 <- f1; v2 <- f2; v3 <- f3 } yield (v1, v2, v3)
}


Answer 2:

应用型函子

你所要求的是对未来的一个适用函子。 见scalaz 应用型 Builder模式。 它应该是相当琐碎推出自己的背部zip

(f0 |@| f1 |@| f2)(g) //g is function (Class1, Class2, Class3) => Z

这相当于直接应用性:

(f0 <***> (f1, f2))(g)

Scalaz附带来自目标形成一个元组香蕉括号方法和参数(即你要的)。 所以,你的解决方案将是:

f0 <|**|> (f1, f2) //that. is. all.

你得到这一切只需通过定义为以下类型类类型类一个实例:

trait Apply[Z[_]] {
  def apply[A, B](f: Z[A => B], a: Z[A]): Z[B]
}

因此,对于未来这个样子:

implicit val FutureApply = new Apply[Future] {
  def apply[A, B](f: Future[A => B], a: Future[A]): Future[B] = 
    (f zip a) map { case (fn, a1) => fn(a1) }
  }
}

(其实你需要PureFunctor以及还不如实行。 Bind ,而你在它-见附录)

关于这种模式的最大好处是,你将开始看到无处不它(例如,在Option中, Validation ,在List等)。 例如,2个流的笛卡尔乘积是:

s1 <|*|> s2

笔记

所有上述假设scalaz 6,无疑scalaz 7 2.10将与这些类型类默认发货。 Pure已改名为Pointed的scalaz7。


附录

为今后其他类型的类实例:

implicit val FuturePure = new Pure[Future] {
  def pure[A](a: =>A): Future[A] = Future { a }
}
implicit val FutureBind = new Bind[Future] {
  def bind[A, B](a: Future[A], f: A => Future[B]): Future[B] = a flatMap f
}
implicit val FutureFunctor = new Functor[Future] {
  def map[A, B](a: Future[A], f: A => B): Future[B] = a map f
}


Answer 3:

如果您使用的阿卡看看数据流: http://doc.akka.io/docs/akka/2.0.2/scala/dataflow.html

您需要使用分隔延续插件(但多数民众赞成容易SBT)则是这样的:

val f:Future[(Class1,Class2,Class3)] = flow {
  val f0 = process1
  val f1 = process2
  val f2 = process3
  (f0(), f1(), f2())
}

应该编译。

在build.sbt:

autoCompilerPlugins := true

addCompilerPlugin("org.scala-lang.plugins" % "continuations" % "2.9.1")


Answer 4:

你也可以使用猫:

import cats._
import cats.instances.future._

有这样的一些有用的方法:

首先更普遍的选项:

Applicative[Future].map3(f0, f1, f2){ 
  (f0r, f1r, f2r) => //do something with results
}

和简单的:)那将只返回元组的未来[(f0.type,f1.type,f2.type)

Applicative[Future].tuple3(f0, f1, f2)


文章来源: How to combine Futures of different types into a single Future without using zip()