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

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

Related

haskell expression evaluation

I am new to haskell and I would like you to give me your suggestion about the following haskell expression evaluation.
f xs = foldr (\x n->n+1) 0 xs
function
f [1, 4]
Evaluation
(\x n->n+1) 1 (foldr (\x n->n+1) 0 [4])
= (foldr (\x n->n+1) 0 [4]) + 1
= ((\x n->n+1) 4 (foldr (\x n->n+1) 0 [4])) + 1
= (foldr (\x n->n+1) 0 [] + 1) + 1
= (0 + 1) + 1
= 1 + 1
= 2
First of all we need the foldr implementation:
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
now let's try to "trace" our computation f [1, 4]:
f [1, 4] -- rewrite list
f (1:(4:[])) -- replace f function where xs = (1:(4:[]))
foldr (\x n-> (+) n 1 ) 0 (1:(4:[]))
-- using foldr f z (x:xs) = f x (foldr f z xs)
-- where f = (\x n -> (+) n 1), z = 0, x = 1, xs = (4:[])
(\x n ->(+) n 1) 1 ( foldr (\x n -> (+) n 1) 0 (4:[]))
-- lambda function will be evaluated with x = 1, n = ( foldr (\x n -> n+1) 0 (4:[]))
(+) (foldr (\x n -> n+1) 0 (4:[])) 1
-- (+) will try to evaluate first parameter
-- foldr will be applied with f = (\x n -> (+) n 1), z = 0, x = 4, xs = []
(+) ((\x n -> (+) n 1) 4 (foldr (\x n -> (+) n 1) 0 [] )) 1
-- now again the lambda will be evaluated where x = 4 and n = (foldr (\x n -> (+) n 1) 0 [] )
(+) ( (+) (foldr (\x n -> (+) n 1) 0 [] ) 1 ) 1
-- now foldr will be evaluated again but this time first form will be used, so just z counts: f = (\x n -> (+) n 1), z = 0, [] = []
(+) ( (+) ( 0 ) 1 ) 1
-- now just go with the flow
(+) ( (+) 0 1 ) 1
(+) ( 1 ) 1
(+) 1 1
2

Using folds to make a function more elegant

I originally presented my function as a solution where myTakeWhile returns elements of (x:xs) as a list until it reaches an element which the function argument equates to false. After which another solution was presented, which is below.
myTakeWhile :: (a -> Bool) -> [a] -> [a]
myTakeWhile p [] = []
myTakeWhile p (x:xs) = if p x then x : myTakeWhile p xs else []
myTakeWhile :: (a -> Bool) -> [a] -> [a]
myTakeWhile p (x:xs) = foldr (\x acc -> if p x then x : acc else []) [] (x:xs)
I'm having real trouble running through the fold step by step in my head, especially the counter-intuition of a right fold starting from the left side of the list in the tests I have tried below.
*Assignment1a> myTakeWhile (\x -> x `mod` 2 == 0) [1, 2, 3, 4, 5]
[]
*Assignment1a> myTakeWhile (\x -> x `mod` 2 == 0) [8, 10, 12, 1, 2, 3, 4, 5]
[8,10,12]
Fundamentally I somewhat understand how a fold works through looking at lecture notes. However the fold in context is confusing me, even with the currying removed! How do I go about understanding this fold step by step?
let's do it step by step with the example [8,10,12,1,2].
I assume you understand that you can think about a right-fold foldr f a xs by replacing : with `f` and [] with a in xs:
with f = \x acc -> if even x then x:acc else []:
myTakeWhile even [8,10,12,1,2]
= foldr f [] [8,10,12,1,2]
= foldr f [] (8:10:12:1:2:[])
{ replace the : with `f` and [] with [] }
= 8 `f` (10 `f` (12 `f` (1 `f` (2 `f` []))))
{ 2 is even so f 2 [] = 2:[] }
= 8 `f` (10 `f` (12 `f` (1 `f` (2:[]))))
{ 2:[] = [2] }
= 8 `f` (10 `f` (12 `f` (1 `f` [2])))
{ 1 is odd so f 1 [2] is [] }
= 8 `f` (10 `f` (12 `f` ([])))
{ ([]) = [] }
= 8 `f` (10 `f` (12 `f` []))
{ 12 is even so f 12 [] = 12:[] }
= 8 `f` (10 `f` (12:[]))
{ 12:[] = [12] }
= 8 `f` (10 `f` [12])
{ 10 is odd so f 10 [12] = 10:12 }
= 8 `f` (10:[12])
{ 10:[12] = [10,12] }
= 8 `f` [10,12]
{ 8 is odd so f 8 [10,12] is 8:[10,12] }
= 8:[10,12]
{ 8:[10,12] = [8,10,12] }
= [8,10,12]
how does foldr work
to see why foldr does the replacement you just have to remember the definition:
foldr _ a [] = a
foldr f a (x:xs) = f x (foldr f a xs) = x `f` (foldr f a xs)
the trick is to think recursive (with induction):
foldr f a []
{ definition }
a
foldr f b (b:bs)
{ definition foldr x <- b; xs <- bs }
= b `f` (foldr f a bs)
{ induction/recursion }
= b `f` { bs with : replaced by `f` and [] by a }
expanded example
foldr f a [b1,b2]
{ [b1,b2] = b1:b2:[] }
= foldr f a (b1:b2:[])
{ definition foldr x <- b1; xs <- b2:[]}
= b1 `f` (foldr f a (b2:[]))
{ definition foldr x <- b2; xs <- []}
= b1 `f` (b2 `f` (foldr f a []))
{ definition foldr empty case }
= b1 `f`(b2 `f` a)

foldr result - Haskell

Could you explain me step by step the result of the second instruction?
I know how foldr works in this cases:
foldr (*) 1 [-3..-1]
-6
But I don't know how to deal with the function (\y z -> y*3 + z) in a foldr expression.
foldr (\y z -> y*3 + z) 0 [1..4]
30
Let's look at the definition of foldr:
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
Now, in your example,
f y z = y*3 + z
So, just using the definitions:
foldr f 0 [1..4] =
f 1 (foldr f 0 [2..4]) =
f 1 (f 2 (foldr f 0 [3,4])) =
f 1 (f 2 (f 3 (foldr f 0 [4]))) =
f 1 (f 2 (f 3 (f 4 (foldr f 0 [])))) =
f 1 (f 2 (f 3 (f 4 0))) =
f 1 (f 2 (f 3 12))) =
f 1 (f 2 21) =
f 1 27 =
30

Calculation steps in Haskell foldr

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.

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