了解传递给折叠的咖喱函数

ElB*_*ulP 5 scala fold monoids

我在从Scala的Book 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)
Run Code Online (Sandbox Code Playgroud)

foldMap正在期待一个功能f: A => B

在中foldRight,当f您被咖喱处理时A => (B => B),我想f.curried它是因为与相同而工作了(A => B => B),因此foldRight传递给foldMap它所期望的(具有type的函数A => B),然后,接下来发生的foldMap是调用它并返回一个函数B => B,而当公司z在进场(f.curried)(z)调用函数B => B与参数z,以获得最后的B

我对吗?对于我来说,对此代码进行推理有点麻烦。

注意:如果您想使用它,这是一个scalafiddle

Ben*_*tou 2

嗯,你对我来说似乎很全面。尽管如此,我还是想澄清一些观点:

  • 我宁愿说“所以我想它f.curried是有效的,因为与”A => (B => B)相同(这里不明确的,你基本上谈论的是结果类型,而不是)(A => B => B)f.curriedz
  • 我宁愿在这里放一个点而不是逗号:“foldMap正在期待一个函数 f: A => B 。在foldRight,... ”以及几乎所有其他地方。更短的短语,更清晰的解释。
  • 什么可能是一个错误,(什么让你感到困惑?)是(f.curried)(z)它本身不能工作,并且在之后不会被调用foldMap(as, endoMonoid[B])。首先foldMap(as, endoMonoid[B])(f.curried)被调用,然后是(z)。第一个返回B => B并与第二个返回一起调用B