Haskell:为什么`par`定义它的方式?

usr*_*usr 5 parallel-processing multithreading haskell par

par 声明为:

par  :: a -> b -> b
Run Code Online (Sandbox Code Playgroud)

请注意,该论点被抛弃了.为了使用par,你需要多次使用同一个表达式.

如果它的目的是并行执行a和b,为什么它不是这样定义的?:

par  :: (a, b) -> (a, b)
Run Code Online (Sandbox Code Playgroud)

获取(未评估的)表达式的元组并返回相同的表达式 - 同时它们可能在后台线程上实现.

似乎后者的模型比前者简单.为什么选择这样的设计?

Dan*_*her 8

在前者中,您可以轻松地激发两次以上的计算,

c1 `par` c2 `par` c3 `par` c4 `pseq` something c1 c2 c3 c4
Run Code Online (Sandbox Code Playgroud)

这在后者中相当麻烦.

  • 诀窍是你在最终值中使用引发计算的结果,这也得到了一个"pseq". (5认同)

ja.*_*ja. 7

您建议的tupled版本可以在Control.Parallel.Strategies中找到parTuple2,类型如下:

evalTuple2 :: Strategy a -> Strategy b -> Strategy (a, b)
Run Code Online (Sandbox Code Playgroud)

至于为什么par是这样设计的,par是'更高级别',正如Real World Haskell的第24章所讨论的那样,他们将快速排序并行化:

我们代码的这些变化对于我们不需要说的所有事情都是非常了不起的.

  • 要使用多少个核心.
  • 什么线程可以相互通信.
  • 如何在可用核心之间划分工作.
  • 哪些数据在线程之间共享,哪些是私有的.
  • 如何确定所有参与者何时完成.

确定性并行性的Monad中,Marlow,Newton和Peyton Jones写道:

par运算符是一种有吸引力的语言设计,因为它利用了懒惰评估和期货之间的重叠.为了实现延迟评估,我们必须对尚未评估但稍后可能需要其值的表达式进行表示; 类似地,未来是一种计算,其价值是并行评估的,我们可能会等待.因此,par被认为是一种机制,用于将惰性计算注释为可能的并行计算表,实际上将惰性计算转化为未来