了解传递给 fold 的柯里化函数

Understanding curried function passed in to fold

我无法理解 this Scala 中 FP 中的代码。这是代码:

trait Monoid[A] {
  def op(a1: A, a2: A): A
  def zero: A
}

def endoMonoid[A]: Monoid[A => A] = new Monoid[A => A] {
    def op(f: A => A, g: A => A) = f compose g
    val zero = (a: A) => a
}

def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B =
  as.foldLeft(m.zero)((b, a) => m.op(b, f(a)))

// The function type `(A, B) => B`, when curried, is `A => (B => B)`.
  // And of course, `B => B` is a monoid for any `B` (via function composition).
def foldRight[A, B](as: List[A])(z: B)(f: (A, B) => B): B =
    foldMap(as, endoMonoid[B])(f.curried)(z)

foldMap 期待函数 f: A => B.

foldRight 中,当 f 被柯里化时你有 A => (B => B),所以我认为 f.curried 正在工作,因为它与 (A => B => B) 相同,所以 foldRight 传递给 foldMap 它所期望的(类型为 A => B 的函数),然后,接下来发生的是 foldMap 被调用并返回一个函数 B => B,这就是 z(f.curried)(z) 中发挥作用的时候,您使用参数 z 调用函数 B => B 以获得最终的 B

我说得对吗?对我来说这段代码的推理有点复杂。

注意:这里有一个scalafiddle如果你想玩的话。

好吧,你对我来说似乎很全面。尽管如此,我还是要澄清几点:

  • 我宁愿说"so I suppose f.curried is working because A => (B => B) is the same as (A => B => B)"(在这里模棱两可,你说的是f.curried 基本上是结果类型,而不是 z)
  • 我宁愿在这里放一个点而不是逗号:“foldMap 期待函数 f: A => B 。在 foldRight 中,... " 以及几乎所有其他地方。更短的短语,更清晰的解释。
  • 可能是什么错误,(让您感到困惑的是什么?)是 (f.curried)(z) 不能单独工作并且不会在 foldMap(as, endoMonoid[B])。首先调用 foldMap(as, endoMonoid[B])(f.curried),然后调用 (z)。第一个 returns B => B 并调用第二个 returns B.