为什么折叠咖喱?

时间:2016-06-27 19:09:53

标签: scala

启动值是否只是op参数列表中的参数?

食物在列表中定义为

  

def fold [A1>:A](z:A1)(op:(A1,A1)⇒A1):A1折叠元素   使用指定的关联二进制文件的此可遍历或迭代器   操作

将折叠定义为

的含义是什么?
  

def fold [A1>:A](op:(z:A1,A1,A1)⇒A1):A1

因此,在此版本中,初始值作为值传递给函数,而不是在单独的参数列表中进行curry。

1 个答案:

答案 0 :(得分:5)

如果您希望激发foldLeft的特定签名,那么首先检查reduceLeft可能是值得的。

// Slightly simplified to remove the supertype constraint
def reduceLeft(f: (A, A) => A): A

reduceLeft将整个集合整理成一个单独的元素,它将一个函数作为一个参数,告诉它如何将集合中的每个新元素压缩到目前为止的内容。

然而,有一个问题。 reduceLeft是偏袒的。特别是如果集合是空的,reduceLeft无处可以开始压扁事物。因此,我们可以通过告诉reduceLeft从哪里开始来实现它。所以我们给reduceLeft一个额外的参数。

def reduceLeftTotal(initial: A, f: (A, A) => A): A

请注意,如果我们将initial作为f的另一个参数,我们就不会修复reduceLeft的偏好。如果this是一个空集合,我们仍然会爆炸。

// This doesn't get us what we want. Where does the initial `A` come from?
def reduceLeftNotWhatWeWant(f: (A, A, A) => A): A

好的,既然我们已经有了reduceLeftTotal,那么就会有一个新的推广途径。为什么我们要将我们集合中所有元素压缩到的东西必须与元素具有相同的类型?答案是它没有!

def generalReduceLeftTotal[B](initial: B, f: (B, A) => A): B

最后,因为先前参数列表中的类型信息,而不是同一列表中的先前参数,可用于帮助Scala的类型推断,我们可以通过currying来减少我们需要的显式类型注释的数量。

// And we're back to foldLeft!
def foldLeft[B](initial: B)(f: (B, A) => A): B