Calculation steps in Haskell foldr - haskell

Does anybody know the steps of haskell 'foldr' use of function?
GHCI Command Window:
foldr (\x y -> 2*x + y) 4 [5,6,7]
The result after evaluation:
40
Steps on this,
Prelude> foldr (\x y -> 2*x + y) 4 [5,6,7]
6 * 2 + (7 * 2 + 4)
12 + 18 = 30
5 * 2 + 30 = 40 v

One definition of foldr is:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f acc [] = acc
foldr f acc (x:xs) = f x (foldr f acc xs)
The wikibook on Haskell has a nice graph on foldr (and on other folds, too):
: f
/ \ / \
a : foldr f acc a f
/ \ -------------> / \
b : b f
/ \ / \
c [] c acc
I.e. a : b : c : [] (which is just [a, b, c]) becomes f a (f b (f c acc)) (again, taken from wikibook).
So your example is evaluated as let f = (\x y -> 2*x + y) in f 5 (f 6 (f 7 4)) (let-binding only for brevity).

You can actually easily visualize it for yourself:
import Text.Printf
showOp f = f (printf "(%s op %s)") "0" ["1","2","3"]
then
Main> showOp foldr
"(1 op (2 op (3 op 0)))"
Main> showOp foldl
"(((0 op 1) op 2) op 3)"
Main> showOp scanl
["0","(0 op 1)","((0 op 1) op 2)","(((0 op 1) op 2) op 3)"]

[This was supposed to be a comment on delnan's remark, but was too wordy...]
Yoon, you can open a private 'conversation' with lambdabot on the #haskell irc (e.g. at http://webchat.freenode.net/ ). She has a simple reflection ability, so you can type meaningless letters, e.g.
Yoon: > foldr (\x y -> 2*x + y) o [a,b,c,d]
lamdabot: 2 * a + (2 * b + (2 * c + (2 * d + o)))
This says what is evaluated, but as Edka points out you get a picture of the order of evaluation from say
Yoon: > reverse (scanr (\x y -> 2*x + y) o [a,b,c,d])
lambdabot: [o,2 * d + o,2 * c + (2 * d + o),2 * b + (2 * c + (2 * d + o)),2 * a + (2 * b + (2 * c + (2 * d + o)))
I remember imprinting some good lessons playing around with foldr, foldl, scanr, scanl and this clever device.

Related

Describing the first few evaluation steps of a given foldr function

The following function is given:
mystery a b c xs =
foldr (\x rec a b -> rec x (b + c)) (\a b -> a + b - c) xs a b
I know what the function does roughly but I have a hard time really understanding the intermediate steps. I picked following example:
mystery 1 2 3 [1, 2, 3]
Especially the use of rec is giving me a hard time. I assume that one of the final steps looks like this:
(\a b -> 3 + (b + 3 + 3 + 3) - 3) [] 1 2
So the output is 11. Could someone describe the first few steps of the execution? What happens after:
foldr (\x rec a b -> rec x (b + 3)) (\a b -> a + b - 3) [1, 2, 3] 1 2
The key here is that the foldr operation is constructing a function, then applying it to a and b; we can clarify it by adding parentheses:
mystery a b c xs =
(foldr (\x rec a b -> rec x (b + c)) (\a b -> a + b - c) xs) a b
If the xs list is empty, you get simply the initial function \a b -> a + b - c, which is then applied to a and b.
if it is not empty, then it makes succesive transformations to that function (in each iteration, "rec" is the previous function, which is used to construct a new one).
To illustrate, let's run the foldr by hand for mystery 1 2 3 [1, 2, 3];
initially, we have:
foldr (\x rec a b -> rec x (b + 3)) (\a b -> a + b - 3) [1,2,3]
Applying the equations for foldr:
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
Reduces the expression to:
(\rec a b -> rec 1 (b + 3)) (foldr (\x rec a b -> rec x (b + 3)) (\a b -> a + b - 3) [2,3])
Repeating for the next value in the list we get:
(\rec a b -> rec 1 (b + 3)) (\rec a b -> rec 2 (b + 3)) (foldr (\x rec a b -> rec x (b + 3)) (\a b -> a + b - 3) [3])
Then, for the last one:
(\rec a b -> rec 1 (b + 3)) (\rec a b -> rec 2 (b + 3)) (\rec a b -> rec 3 (b + 3)) (\a b -> a + b - 3)
We need to compose those functions, to create the final function - replacing "rec" with the previous function:
(\rec a b -> rec 1 (b + 3)) (\rec a b -> rec 2 (b + 3)) (\rec a b -> rec 3 (b + 3)) (\a b -> a + b - 3)
=> (\rec a b -> rec 1 (b + 3)) (\rec a b -> rec 2 (b + 3)) (\a b -> (\a b -> a + b - 3) 3 (b + 3))
=> (\rec a b -> rec 1 (b + 3)) (\rec a b -> rec 2 (b + 3)) (\a b -> 3 + (b + 3) - 3))
=> (\rec a b -> rec 1 (b + 3)) (\a b -> (\a b -> 3 + (b + 3) - 3)) 2 (b + 3))
=> (\rec a b -> rec 1 (b + 3)) (\a b -> 3 + ((b + 3) + 3) - 3))
=> \a b -> (\a b -> 3 + ((b + 3) + 3) - 3)) 1 (b + 3)
=> \a b -> 3 + (((b + 3) + 3) + 3) - 3)
=> \a b -> b + 9
then, we apply \a b -> b + 9 to the original "a" and "b" (which are 1 and 2), and get 2 + 9 = 11
Substituting the definition for foldr, the function reveals itself to be
mystery a b c xs =
= foldr (\x rec a b -> rec x (b + c)) (\a b -> a + b - c) xs a b
= let { g x r a b = r x (b + c); z a b = a + b - c } in
foldr g z xs a b
=> foldr g z [] a b = z a b = a + b - c
=> foldr g z [x1,x2,...,xn] a b
= g x1 (foldr g z [x2,...,xn]) a b -- g x r a b = r x (b+c)
= foldr g z [x2,...,xn] x1 (b+c)
= foldr g z [x3,...,xn] x2 (b+c*2)
= foldr g z [ ] xn (b+c*n) = xn + b + c*n - c
= last (a:xs) + b + c * (length xs - 1)
Naming the two lambda functions, using short names, makes it much easier to handle the expressions visually.
When the folding function given to foldr takes more than two parameters, it's often really a foldl in disguise. Let's see if that's true here.
mystery a b c xs = foldr (\x rec a b -> rec x (b + c)) (\a b -> a + b - c) xs a b
Uncurry the two "extra" arguments to the folding function:
mystery a b c xs = foldr (\x rec (a,b) -> rec (x,b + c)) (\(a,b) -> a + b - c) xs (a,b)
Extract function f out of the folding function, and finalStep from the nil case:
mystery a b c xs = foldr (\x rec z -> rec (f z x)) finalStep xs (a,b)
where
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Replace foldr with explicit recursion:
mystery a b c xs = go xs (a,b)
where
go [] = finalStep
go (x:xs) = \z -> go xs (f z x)
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Move the call to finalStep outside of go:
mystery a b c xs = finalStep $ go xs (a,b)
where
go [] = id
go (x:xs) = \z -> go xs (f z x)
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Eta-expand go and reverse the order of the arguments:
mystery a b c xs = finalStep $ go (a,b) xs
where
go z [] = z
go z (x:xs) = go (f z x) xs
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Now, go is exactly the definition of foldl f, so replace it with that:
mystery a b c xs = finalStep $ foldl f (a,b) xs
where
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Now we have a very simple fold operation that can be trivially worked through. The key takeaway from the above is the fact that foldr (\x rec -> rec . f x) finalStep xs z and finalStep $ foldl (flip f) z xs are the same, for any f, z, and xs.

foldr in Haskell: confusion [duplicate]

This question already has an answer here:
Haskell foldr with function
(1 answer)
Closed 5 years ago.
I just have a question about the usage of foldr.
Say I want to use foldr in this way:
foldr (\x y -> (x + y)/2) 2 [4,5,6]
Is y in this case represents each element of the list?
In particular, let's unwrap this function.
we have (x = 2, y= 6) -> (2+6)/2 = 4.
Next, do we have x=4, y = 5?
I am asking a simplify version of what I really want to ask. Here, the content of x and y represents matter a lot because in my application, I have a function that takes 1st argument as type a, and second argument as type b. Thus, I do need to know whats going on under-the hood.
Say I want to use foldr in this way:
foldr (\x y -> (x + y)/2) 2 [4,5,6]
Is y in this case represents each element of the list?
One way of figuring it out is looking at the type of foldr:
GHCi> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
The structure being folded has type t a for some Foldable t (in your case, you have a list, and so t is []), and its elements have type a. The result accumulated through the fold has type b. The binary function used for folding has type a -> b -> b, so the elements are passed as its first argument, and the accumulated value, as its second.
Another way of figuring out is by reading the actual implementation of foldr for lists (I found this by looking for the Foldable instance of lists and then following the source links). You might want to try that, to see how one picture corresponds to the other.
foldr f startingValue (x:xs) expands to f x (foldr f startingValue xs), and foldr f startingValue [] expands to startingValue so in your case:
foldr (\x y -> (x + y)/2) 2 [4,5,6]
(\x y -> (x + y)/2) 4 (foldr (\x y -> (x + y)/2) 2 [5,6])
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 (foldr (\x y -> (x + y)/2) 2 [6]))
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 ((\x y -> (x + y)/2) 6 (foldr (\x y -> (x + y)/2) 2 [])))
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 ((\x y -> (x + y)/2) 6 2))
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 4)
(\x y -> (x + y)/2) 4 4.5
4.25
It might be easier to see with f x y = (x + y)/2:
foldr f 2 [4,5,6]
f 4 (foldr f 2 [5,6])
f 4 (f 5 (foldr f 2 [6]))
f 4 (f 5 (f 6 (foldr f 2 [])))
f 4 (f 5 (f 6 2))
f 4 (f 5 4)
f 4 4.5
4.25
If you understand how cons lists are constructed (using :), you can think of foldr as replacing all the : with the function you provide.

Recursive lambda in Haskell

Let's see analyse code for factorial in Haskell using lambda function:
y f x = f (y f) x
factorial = y (\t n -> if n == 1 then 1 else n * t(n-1))
And I cannot understand how does it works. I know that it is connected with lambda calculus but nowadays I am not familiar with that so I have to understand without it or with minimal knowledge.
My doubt is:
What is f in definition of factorial? I mean this f: y f x = f (y f) x.
So what is f here? y (\t n -> if n == 1 then 1 else n * t(n-1))
Please explain me that, maybe expand recursion?
the fin factorial is the (\t n -> if n == 1 ...) lambda
y is a so called fix-point combinator and it's used to enable recursive definitions in the lambda-calculus (it applies f to it's argument again and again recursively)
to understand how it works you can just do some evaluation by hand:
factorial 3
= y (\t n -> ...) 3
{ def y and y (\t n -> ...) = factorial by eta-red. }
= (\t n -> ...) factorial 3
{ t = factorial, n = 3 -> else case }
= 3 * factorial 2
= 3 * (y (\t n -> ...) 2)
= 3 * ((\t n -> ...) factorial 2)
= { t = factorial, n = 2 -> else case }
= 3 * (2 * factorial 1)
= 3 * (2 * (y (\t n -> ...) 1))
= 3 * (2 * ((\t n -> ...) factorial 1)))
{ t = factorial n = 1 -> then case }
= 3 * (2 * 1)
= 6
y is the fixed-point combinator, also known as the y-combinator. In
factorial = y (\t n -> if n == 1 then 1 else n * t(n-1))
the lambda (\t n -> if n == 1 then 1 else n * t(n-1)) is bound to f in the definition of y. You can then do the expansion:
(\t n -> if n == 1 then 1 else n * t(n-1)) (y (\t n -> if n == 1 then 1 else n * t(n-1)))
so inside the lambda, t will be bound to the lambda itself, which allows it to call itself recursively.
Perhaps it's easier if you write out the y combinator thus, with two eta-expansions:
y :: ((a->b) -> a->b) -> a->b
y f x a = f (\q a' -> y f q a') x a
So f basically gets the recursive call (with a' in place of a) as its first argument.

Haskell function foldl (\x y -> x*2 + y*2) 0 behavior

I stuck with a problem. What's difference between these two functions:
foldl (\x y -> x*2 + y*2) 0 [1,2,3] = 22
foldr (\x y -> x*2 + y*2) 0 [1,2,3] = 34
foldl (\x y -> x*2 + y*2) 0 [1,2,3] ⇒ f( f( f(0,1),2 ),3 )
foldr (\x y -> x*2 + y*2) 0 [1,2,3] ⇒ f( 3,f( 2, f(1,0) ) )
where f = \x y -> x*2 + y*2.
I understand result of foldl:
x = f(0,1) = 2
y = f(x,2) = 8
z = f(y,3) = 22
But why does foldr sum after result of each step?
2 + 8 + 22 = 34
You have the foldr evaluation backwards. It should look like this:
foldr f 0 [1,2,3] == f 1 (f 2 (f 3 0))
For contrast, the foldl evaluation (which is correct in your question) looks like
foldl f 0 [1,2,3] == f (f (f 0 1) 2) 3
If you feel comfortable thinking of the list [1,2,3] as being the same as 1:2:3:[], this diagram of foldr might help:
Your definition of foldr is a little off. Instead of f( 3,f( 2, f(1,0) ) ), it should be f( 1,f( 2, f(3,0) ) ).
foldl f z [1,2,3] = ((0 `f` 1) `f` 2) `f` 3
= ((0*2 + 1*2) `f` 2) `f` 3
= (2 `f` 2) `f` 3
= (2*2 + 2*2) `f` 3
= 8 `f` 3
= 8*2 + 3*2
= 22
foldr f z [1,2,3] = 1 `f` (2 `f` (3 `f` 0))
= 1 `f` (2 `f` (3*2 + 0*2))
= 1 `f` (2 `f` 6)
= 1 `f` (2*2 + 6*2)
= 1 `f` 16
= 1*2 + 16*2
= 34

Where do theses values come from in this haskell function?

Let's say I have the following function:
sumAll :: [(Int,Int)] -> Int
sumAll xs = foldr (+) 0 (map f xs)
where f (x,y) = x+y
The result of sumAll [(1,1),(2,2),(3,3)] will be 12.
What I don't understand is where the (x,y) values are coming from. Well, I know they come from the xs variable but I don't understand how. I mean, doing the code above directly without the where keyword, it would be something like this:
sumAll xs = foldr (+) 0 (map (\(x,y) -> x+y) xs)
And I can't understand, in the top code, how does the f variable and (x,y) variables represent the (\(x,y) -> x+y) lambda expression.
Hopefully this will help. The key is that f is applied to the elements of the list, which are pairs.
sumAll [(1,1),(2,2),(3,3)]
-- definition of sumAll
= foldr (+) 0 (map f [(1,1),(2,2),(3,3)])
-- application of map
= foldr (+) 0 (f (1,1) : map f [(2,2),(3,3)])
-- application of foldr
= 0 + foldr (+) (f (1,1)) (map f [(2,2),(3,3)])
-- application of map
= 0 + foldr (+) (f (1,1)) (f (2,2) : map f [(3,3)])
-- application of foldr
= 0 + (f (1,1) + foldr (+) (f (2,2)) (map f [(3,3)]))
-- application of f
= 0 + (2 + foldr (+) (f (2,2)) (map f [(3,3)]))
-- application of map
= 0 + (2 + foldr (+) (f (2,2)) (f (3,3) : map f []))
-- application of foldr
= 0 + (2 + (f (2,2) + foldr (+) (f (3,3)) (map f [])))
-- application of f
= 0 + (2 + (4 + foldr (+) (f (3,3)) (map f [])))
-- application of map
= 0 + (2 + (4 + foldr (+) (f (3,3)) []))
-- application of foldr
= 0 + (2 + (4 + f (3,3)))
-- application of f
= 0 + (2 + (4 + 6))
= 0 + (2 + 10)
= 0 + 12
= 12
In Haskell, functions are first class datatypes.
This means you can pass functions around like other types of data such as integers and strings.
In your code above you declare 'f' to be a function, which takes in one argumenta (a tuple of two values (x,y)) and returns the result of (x + y).
foldr is another function which takes in 3 arguments, a binary function (in this case +) a starting value (0) and an array of values to iterator over.
In short 'where f (x,y) = x + y' is just scoped shorthand for
sumAll :: [(Int,Int)] -> Int
sumAll xs = foldr (+) 0 (map myFunctionF xs)
myFunctionF :: (Int,Int) -> Int
myFunctionF (x,y) = x + y
Edit: If your unsure about how foldr works, check out Haskell Reference Zvon
Below is an example implementation of foldl / map.
foldl :: (a -> b -> b) -> b -> [a] -> b
foldl _ x [] = x
foldl fx (y:ys) = foldl f (f y x) ys
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = (f x) : (map f xs)
Not an answer, but I thought I should point out that your function f:
f (x, y) = x + y
can be expressed as
f = uncurry (+)

Resources