I am having problems understanding this code from the Book FP in Scala. Here is the code:
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
is expecting a function f: A => B
.
In foldRight
, when f
is curried you have A => (B => B)
, so I suppose f.curried
is working because it is the same as (A => B => B)
, so foldRight
is passing in to foldMap
what it expect (a function with type A => B
), then, what happends next is that foldMap
is called and its returning a function B => B
, and that's when z
comes into play in (f.curried)(z)
you call the function B => B
with the argument z
to get the final B
.
Am I right? it is a litle complicated to reason about this code for me.
NOTE: Here is a scalafiddle if you want to play with it.