并行中的scala中的map3

时间:2017-05-29 09:47:38

标签: scala functional-programming

def map2[A,B,C] (a: Par[A], b: Par[B]) (f: (A,B) => C) : Par[C] =
(es: ExecutorService) => {
  val af = a (es)
  val bf = b (es)
  UnitFuture (f(af.get, bf.get))
}

def map3[A,B,C,D] (pa :Par[A], pb: Par[B], pc: Par[C]) (f: (A,B,C) => D) :Par[D]  =
map2(map2(pa,pb)((a,b)=>(c:C)=>f(a,b,c)),pc)(_(_))

我有map2,需要根据map2生成map3。我在GitHub中找到了解决方案,但很难理解。任何人都可以看到它并解释map3以及它的作用())?

2 个答案:

答案 0 :(得分:3)

在纯粹的抽象层面上,map2意味着您可以并行运行两个任务,这本身就是一项新任务。为map3提供的实现是:并行运行(包括并行运行两个第一个任务的任务)和(第三个任务)。

现在回到代码:首先,让我们给所有创建的对象命名(为了清晰起见,我还扩展了_符号):

def map3[A,B,C,D] (pa :Par[A], pb: Par[B], pc: Par[C]) (f: (A,B,C) => D) :Par[D]  = {
  def partialCurry(a: A, b: B)(c: C): D = f(a, b, c)
  val pc2d: Par[C => D] = map2(pa, pb)((a, b) => partialCurry(a, b))
  def applyFunc(func: C => D, c: C): D = func(c)
  map2(pc2d, pc)((c2d, c) => applyFunc(c2d, c)
}

现在请记住map2需要两个Par[_],以及一个合并最终值的函数,以获得结果的Par[_]

第一次使用map2(内部版本)时,您将前两个任务并行化,并将它们组合成一个函数。实际上,使用f,如果您具有类型A的值和类型B的值,则只需要类型C的值来构建类型{ {1}},这恰恰意味着DpartialCurry(a, b)类型的函数(C => D本身属于partialCurry类型)。 现在您再次有两个(A, B) => C => D类型的值,因此您可以再次Par[_],并且只有一种自然方式可以将它们组合起来以获得最终值。

答案 1 :(得分:0)

上一个答案是正确的,但我发现这样子更容易:

  def map3[A, B, C, D](a: Par[A], b: Par[B], c: Par[C])(f: (A, B, C) => D): Par[D] = {
    val f1 = (a: A, b: B) => (c: C) => f(a, b, c)
    val f2: Par[C => D] = map2(a, b)(f1)
    map2(f2, c)((f3: C => D, c: C) => f3(c))
  }

创建一个函数f1,它是f的一个版本,其中部分应用了前2个自变量,然后我们可以map2来使用abC => D上下文(Par)中为我们提供类型为f1的函数。

最后,我们可以使用f2c作为map2的参数,然后将f3C => D)应用于c给我们一个D中的Par

希望这对某人有帮助!