View difference between Paste ID: uN1vDUcR and qkwXkwLr
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))