Scala 向右折叠和向左折叠

Scala fold right and fold left

我正在尝试学习函数式编程和 Scala,所以我正在阅读 Chiusano 和 Bjarnason 的 "Functional Programming in Scala"。我无法理解 fold left 和 fold right 方法在列表的情况下的作用。我环顾四周,但没有找到对初学者友好的东西。所以书上提供的代码是:

def foldRight[A,B](as: List[A], z: B)(f: (A, B) => B): B = as match {
  case Nil => z
  case Cons(h, t) => f(h, foldRight(t, z)(f))
}

def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match {
  case Nil => z
  case Cons(h,t) => foldLeft(t, f(z,h))(f)
}

Cons 和 Nil 是:

case class Cons[+A](head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]

那么左右折到底有什么作用呢?为什么需要 "utility" 方法?还有许多其他方法使用它们,我也很难理解它们,因为我不了解这两个。

假设您有一个数字列表,并且想要将它们全部相加。你会怎么做? 您将第一个和第二个相加,然后取其结果,将其添加到第三个,取其结果,将其添加到第四个......等等。

这就是让我们做的事情。

List(1,2,3,4,5).foldLeft(0)(_ + _)

“+”是您要应用的函数,第一个操作数是迄今为止对元素应用的结果,第二个操作数是下一个元素。 由于第一个应用程序没有 "result so far",因此您提供了一个起始值 - 在本例中为 0,因为它是添加的标识元素。

假设您想将所有列表元素与折叠相乘,那就是

List(1,2,3,4,5).foldLeft(1)(_ * _)

折叠有它自己的 Wikipedia page 你可能想检查一下。

当然还有 foldLeft and foldRight 的 ScalaDoc 条目。

根据我的经验,锻炼直觉的最佳方法之一是在非常简单的示例中查看它的工作原理:

List(1, 3, 8).foldLeft(100)(_ - _) == ((100 - 1) - 3) - 8 == 88
List(1, 3, 8).foldRight(100)(_ - _) == 1 - (3 - (8 - 100)) == -94

可以看到,foldLeft/Right只是将列表的元素和前面申请的结果传递给了第二个括号中的操作。 还应该提到的是,如果将这些方法应用于同一个列表,它们将 return 仅当应用的操作是关联的时才会产生相等的结果。