I am confused about what this means. I understand currying but I can't seem to read the code altogether.
def foldLeft [A,B](xs:List[A], e:B, f:(B,A)=>B): B
I am confused about what this means. I understand currying but I can't seem to read the code altogether.
def foldLeft [A,B](xs:List[A], e:B, f:(B,A)=>B): B
Gaël J
On
Let's dive into this method signature:
foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
foldLeft is a method with 3 parametersA and B are type parametersxs is 1st parameter of the method, of type List[A]e is 2nd parameter, of type Bf is 3rd parameter, of type (B, A) => B
(B, A) => B represents a function taking two parameters of type B and A respectively, and returning a BB is the return type of the methodCopyright © 2021 Jogjafile Inc.
Just a couple of advices.
By the way, there is no currying in
Currying would be if you had
f: B => A => Bordef foldLeft[A, B](xs: List[A])(e: B)(f: (B, A) => B): Bordef foldLeft[A, B]: List[A] => B => ((B, A) => B) => Betc. NowfoldLeftis just a higher-order function (method), i.e. a function accepting another function (f).foldRight/foldLeft:https://en.wikipedia.org/wiki/Fold_(higher-order_function)
Especially look at the pictures how we deconstruct a list and starting from what end we perform our calculations:
foldRight/foldLeftas a just short way to define a recursion (instead of pattern matching a list and making recursive calls).Let's consider an example. Let's have some recursion. For example let's have a wrapper class
And let's transform a list of
Value[A]into a value wrapping a list ofAi.e.List[Value[A]]intoValue[List[A]]. For example we'd like to transformList(Value(1), Value(2), Value(3))intoValue(List(1, 2, 3))(I actually needed such function recently). Surely, we could do this with.mapbut let's pretend that we don't knowmap(it shouldn't be surprising that we can do mapping becausemapcan be expressed viafoldRight/foldLeft).We can do this recursively in two ways (at least). Either simple recursion
or tail recursion with a helper function and accumulator
Very simple. Just wrapping-unwrapping.
Both recursive implementations of
valuesToValuecan be (automatically) re-written withfoldRight/foldLeft. The former recursion can be re-written withfoldRight. The latter recursion (tail one) can be re-written withfoldLeft.Let's re-write the 1st recursion with
foldRight. The value from branchcase Nil => ...becomes the 1st argument offoldRight. The value from branchcase v :: vs => ...becomes the 2nd argument offoldRightif we replace the result of recursive callvaluesToValue(vs)with a new variableres, so in the 2nd argument offoldRightwe'll have a function ofv: Value[A]andres: Value[List[A]]Let's re-write the 2nd recursion (tail one) with
foldLeft.First of all, let's recall that because of currying we can understand the helper
loopas a single-parameter function intoValue[List[A]] => Value[List[A]]Now the value from branch
case Nil => ...becomes the 1st argument offoldLeft. The value from branchcase v :: vs => ...becomes the 2nd argument offoldLeftif we replace the result of recursive callloop(vs)(_)with a new variableres(a function)So, roughly speaking, values from branches
case Nil => ...andcase v :: vs => ...become arguments offoldRight/foldLeftdepending on whether we calculate with simple recursion or tail recursion with accumulator.