Understanding the reduction process of a foldl - haskell

Since I am new in "innermost, outermost" I have problem with understanding the leftmost outermost style.
I would like to understand the reduction processes for the list [5,2,1]
foldl :: ( b -> a -> b ) -> b -> [ a ] -> b
foldl _ e [] = e
foldl f e (x:xs) = foldl f (f e x) xs
foldl (\acc x -> acc ++ [negate x]) [] [5,2,1]

You can inline the definition to get a better understanding of what is going on.
foldl (\acc x -> acc ++ [negate x]) [] [5,2,1]
-- using foldl f e (x:xs) = foldl f (f e x) xs
-- with f = (\acc x -> acc ++ [negate x])
-- e = []
-- x = 5
-- xs = [2,1]
-- replace line 1 with foldl f (f e x) xs
foldl f (f [] 5) [2,1]
foldl f (f (f [] 5) 2) [1]
foldl f (f (f (f [] 5) 2) 1) []
-- using foldl _ e [] = e
f (f (f [] 5) 2) 1
-- in infix style (f [] 5 == [] `f` 5)
(([] `f` 5) `f` 2) `f` 1
In general
foldl (+) 0 [a, b, c] == ((0 + a) + b) + c
foldr (+) 0 [a, b, c] == a + (b + (c + 0))

Related

Using foldr to define map (develop)

Having a hard time understanding fold... Is the expansion correct ? Also would appreciate any links, or analogies that would make fold more digestible.
foldMap :: (a -> b) -> [a] -> [b]
foldMap f [] = []
foldMap f xs = foldr (\x ys -> (f x) : ys) [] xs
b = (\x ys -> (f x):ys)
foldMap (*2) [1,2,3]
= b 1 (b 2 (foldr b [] 3))
= b 1 (b 2 (b 3 ( b [] [])))
= b 1 (b 2 ((*2 3) : []))
= b 1 ((*2 2) : (6 :[]))
= (* 2 1) : (4 : (6 : []))
= 2 : (4 : (6 : []))
First, let's not use the name foldMap since that's already a standard function different from map. If you want to re-implement an existing function with the same or similar semantics, convention is to give it the same name but either in a separate module, or with a prime ' appended to the name. Also, we can omit the empty-list case, since you can just pass that to the fold just as well:
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x ys -> f x : ys) [] xs
Now if you want to evaluate this function by hand, first just use the definition without inserting anything more:
map' (*2) [1,2,3,4]
≡ let f = (*2)
xs = [1,2,3,4]
in foldr (\x ys -> (f x) : ys) [] xs
≡ foldr (\x ys -> (*2) x : ys) [] [1,2,3,4]
Now just prettify a bit:
≡ foldr (\x ys -> x*2 : ys) [] [1,2,3,4]
Now to evaluate this through, you also need the definition of foldr. It's actually a bit different in GHC, but effectively
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
So with your example
...
≡ foldr (\x ys -> x*2 : ys) [] (1:[2,3,4])
≡ (\x ys -> x*2 : ys) 1 (foldr (\x ys -> x*2 : ys) [] [2,3,4])
Now we can perform a β-reduction:
≡ 1*2 : foldr (\x ys -> x*2 : ys) [] [2,3,4]
≡ 2 : foldr (\x ys -> x*2 : ys) [] [2,3,4]
...and repeat for the recursion.
foldr defines a family of equations,
foldr g n [] = n
foldr g n [x] = g x (foldr g n []) = g x n
foldr g n [x,y] = g x (foldr g n [y]) = g x (g y n)
foldr g n [x,y,z] = g x (foldr g n [y,z]) = g x (g y (g z n))
----- r ---------
and so on. g is a reducer function,
g x r = ....
accepting as x an element of the input list, and as r the result of recursively processing the rest of the input list (as can be seen in the equations).
map, on the other hand, defines a family of equations
map f [] = []
map f [x] = [f x] = (:) (f x) [] = ((:) . f) x []
map f [x,y] = [f x, f y] = ((:) . f) x (((:) . f) y [])
map f [x,y,z] = [f x, f y, f z] = ((:) . f) x (((:) . f) y (((:) . f) z []))
= (:) (f x) ( (:) (f y) ( (:) (f z) []))
The two families simply exactly match with
g = ((:) . f) = (\x -> (:) (f x)) = (\x r -> f x : r)
and n = [], and thus
foldr ((:) . f) [] xs == map f xs
We can prove this rigorously by mathematical induction on the input list's length, following the defining laws of foldr,
foldr g n [] = []
foldr g n (x:xs) = g x (foldr g n xs)
which are the basis for the equations at the top of this post.
Modern Haskell has Fodable type class with its basic fold following the laws of
fold(<>,n) [] = n
fold(<>,n) (xs ++ ys) = fold(<>,n) xs <> fold(<>,n) ys
and the map is naturally defined in its terms as
map f xs = foldMap (\x -> [f x]) xs
turning [x, y, z, ...] into [f x] ++ [f y] ++ [f z] ++ ..., since for lists (<>) == (++). This follows from the equivalence
f x : ys == [f x] ++ ys
This also lets us define filter along the same lines easily, as
filter p xs = foldMap (\x -> [x | p x]) xs
To your specific question, the expansion is correct, except that (*2 x) should be written as ((*2) x), which is the same as (x * 2). (* 2 x) is not a valid Haskell (though valid Lisp :) ).
Functions like (*2) are known as "operator sections" -- the missing argument goes into the empty slot: (* 2) 3 = (3 * 2) = (3 *) 2 = (*) 3 2.
You also asked for some links: see e.g. this, this and this.

Recursive definitions of scanl and scanr in Haskell

I have searched but cannot find simple definitions of the functions scanr and scanl, only explanations that they show the intermediate calculations of the functions foldr and foldl (respectively).
I have written a recursive definition for scanl, based on the foldl property foldl f y (x:xs) = foldl f (f y x) xs:
scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f x [] = [x]
scanl' f x (y:ys) = x : scanl' f (f x y) ys
This seems to work. However, there is a type error when I try to apply this analogy with the foldr property foldr f y (x:xs) = f x (foldr f y xs):
scanr' :: (a -> b -> b) -> b -> [a] -> [b]
scanr' _ x [] = [x]
scanr' f x (y:ys) = y : f x (scanr' f x ys)
This fails as the second input for f needs to be a b not a [b]. However, I am unsure how to do this while also recursing on scanr'.
To compute
result = scanr' f x (y:ys)
you must have computed
partialResult = scanr' f x ys
after which you get
result = (y `f` head partialResult) : partialResult
The complete implementation is
scanr' _ x [] = [x]
scanr' f x (y:ys) = (y `f` head partialResult) : partialResult
where partialResult = scanr' f x ys
scanl1 (\acc x -> if x > acc then x else acc)[3,4,5,3,7,9,2,1]
from Learn You A Haskell seems to have only two arguments: the function and the list. Yet it works. It even works if you write it as:
scanl1 (\x acc -> if x > acc then x else acc)[3,4,5,3,7,9,2,1]
Slightly puzzling why works.

foldr lambda representation - Haskell

I understand this representation:
(foldr(\x acc -> x+10*acc) 0 n)
But recently i've come across with this one that i have not seen yet:
(foldr ((+) . aux . (\(a,b,c) -> c)) 0 list)
A brief explanation would be more than welcome!
(.) is function composition operator, (f . g) x = f (g x), so
((+) . aux . (\(a,b,c) -> c)) (a,b,c) d
= ((+) . aux) ((\(a,b,c) -> c) (a,b,c)) d
= ((+) . aux) c d
= (+) (aux c) d
= aux c + d
This means that for (foldr ((+) . aux . (\(a,b,c) -> c)) 0 list) to be a well-typed expression, we must have types list :: [(a,b,c)] and aux :: Num t => c -> t; then the fold of a list [x1,x2,...,xn] is equivalent to
aux3 x1 + (aux3 x2 + (... + (aux3 xn + 0) ...))
where
aux3 (a,b,c) = aux c

Haskell foldr for lists

Given the following example
foldr(\ x y -> ........
if the input is a list for example [1,2,3]
what is x and what is y?
Let's take a look at the type for foldr.
foldr :: (a -> b -> b) -> b -> [a] -> b
Since you're providing the function that uses x and y, you can see from the type that x will be a value from your list ([1,2,3]), and y must be the accumulator value, which you initialize with the second parameter to foldr.
The definition of foldr is
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
You can just apply it directly in your example:
foldr (\x y -> foo x y) z [1,2,3]
=
(\x y -> foo x y) 1 (foldr (\x y -> foo x y) z [2,3])
=
foo 1 (foldr (\x y -> foo x y) z [2,3])
So x is 1 and y is foldr (\x y ...) z [2,3]).
In general you can think of foldr f z as replacing every (:) in a list with f, and the [] with z. So foldr f z [a,b,c,d] = f a (f b (f c (f d z))) (since [a,b,c,d] = (:) a ((:) b ((:) c ((:) d []))).

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