SHOW:
|
|
- or go back to the newest paste.
1 | // replace calls of returned functions by .apply for clarity | |
2 | - | // difference between foldLeft and foldRight is associativity: |
2 | + | // these are our calls to g |
3 | - | foldLeft(List(1,2,3,4), 0)((a,b) => a + b) = ((((0+1)+2)+3)+4) |
3 | + | foldLeftViaFoldRight(List(1,2), 0)(f) |
4 | - | foldRight(List(1,2,3,4), 0)((b, a) => b + a) = (1+(2+(3+(4+0)))) |
4 | + | |
5 | foldRight(List(1,2), b => b)((a,g) => b => g(f(b, a)))(0) | |
6 | - | //So to invert associativity, we build up a function, starting with identity. |
6 | + | (b1 => foldRight(List(2), b => b)((a,g) => b => g(f(b, a))).apply(f(b1, 1)))(0) // (1) |
7 | ||
8 | - | //added types on foldRight, note that foldRight's B is not foldLeft's B, but a function B => B: |
8 | + | // look at inner fold right separately: |
9 | - | def foldLeftViaFoldRight[A,B](l: List[A], z: B)(f: (B,A) => B): B = |
9 | + | foldRight(List(2), b => b)((a,g) => b => g(f(b, a))) |
10 | - | foldRight[A, B => B](l, (b:B) => b)((a,g) => // g is foldRight's accumulator |
10 | + | b2 => foldRight(Nil, b => b)((a,g) => b => g(f(b, a))).apply(f(b2, 2)) |
11 | - | b => g(f(b,a)) // we return a new function that applies f first, then our accumulated function up to now |
11 | + | b2 => (b => b).apply(f(b2, 2)) // we reach zero element, identity |
12 | - | )(z) // the result of our foldRight is B => B, we call it with the zero element to get the result |
12 | + | b2 => f(b2, 2)) |
13 | ||
14 | // insert into (1) | |
15 | (b1 => (b2 => f(b2, 2)).apply(f(b1, 1)))(0) | |
16 | (b2 => f(b2, 2)).apply(f(0, 1))) // apply the function from foldRight to zero value | |
17 | f(f(0, 1), 2)) |