Using foldr to define map (develop) - haskell

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.

Related

What does map' f xs = foldr (\y ys -> (f y):ys) [] xs. mean? [duplicate]

This question already has answers here:
Use foldr to define map in Haskell,
(3 answers)
Closed 3 months ago.
I'm new to Haskell and I want to understand what this syntax means.
This is the context of the function:
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\y ys -> (f y):ys) [] xs
It's defining the map function from the prelude in terms of foldr. I'm confused by what foldr (\y ys -> (f y):ys) [] xs means. Especially the (\y ys -> (f y): ys) part.
In my understanding, y is the first value in the list ys which is the input and the function f is being applied to the y value in the list ys. I understand these values are taken in the context of pattern matching. Kindly correct me if I'm wrong.
Take a look at a simplified definition of foldr (adapted from https://wiki.haskell.org/Foldr_Foldl_Foldl'):
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
The second argument passed to f (ys, in your case) is basically the result of folding the rest of the list, without having to explicitly make the recursive call.
We can compare an explicitly recursive definition of map':
map' f [] = []
map' f (x:xs) = f x : map' xs
to the expansion of your definition of map' using equational reasoning.
map' f (x:xs)
-- by definition of map'
== foldr (\y ys -> f y : ys) [] (x:xs)
-- by definition of foldr
== (\y ys -> f y : ys) x (foldr (\y ys -> f y : ys) [] xs)
-- application of folding function to x...
== (\ys -> f x : ys) (foldr (\y ys -> f y : ys) [] xs)
-- ... and then the recursive fold
== f x : foldr (\y ys -> f y : ys) [] xs
-- by definition of map'
== f x : map' f xs

Haskell - creating a function definition for the function `all` using foldr

I'm trying to create a function definition for the function all using foldr. p is the predicate. I know this can be done:
all p = and . foldr (\x xs -> p x : xs) []
But what I want to do is to shift the function and into the foldr equation. Can this be done?
I've tried the following, which all failed to work:
all p = foldr (\x p -> \ys -> and (p x) ys) True
all p = foldr (\x and -> (\ys -> (p x and ys))) True
all p = foldr (\x ys -> and . (p x) ys) True
Am I falling short in my understanding of how to apply foldr?
We have
all p = and
. foldr (\x xs -> p x : xs) []
= foldr (&&) True -- {y : ys} -> y && {ys} 2-3
. foldr (\x xs -> p x : xs) [] -- {x , xs} -> p x : {xs} 1-2
= foldr (\x xs -> p x && xs) True -- {x , xs} -> p x && {xs} 1---3
because folding replaces each constructor with the specified combination operation (aka reducer), and replacing a cons of an element with a cons of a modified element, and then replacing that cons with (&&), is just replacing a cons of an element with the (&&) of a modified element right away:
a : ( b : ( c : ( d : ( ... )))) _OR_ [] -- | | 1
-- | |
p a : (p b : (p c : (p d : ( ... )))) _OR_ [] -- ↓ | | 2
-- | |
p a && (p b && (p c && (p d && ( ... )))) _OR_ True -- ↓ ↓ 3
In other words, folds compose by fusing their reducer functions, and reducer functions fuse by replacing the {constructors they use} with the next fold's reducer in the chain of folds, so that their corresponding transducers compose (as in Clojure's transducers); thus,
= foldr (reducingWith (&&)) True
. foldr ((mapping p) (:)) []
= foldr ((mapping p) (reducingWith (&&))) True
= foldr ((mapping p . reducingWith) (&&) ) True
-- first map p, then reduce with (&&)
for the appropriate definitions of reducingWith and mapping:
reducingWith cons x xs = cons x xs
mapping f cons x xs = cons (f x) xs
filtering p cons x xs | p x = cons x xs
| otherwise = xs
concatting t cons x xs = foldr cons xs (t x)

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.

Strictness of pattern matching vs. deconstructing

I'm trying to define primitive recursion in term of foldr, as explained in A tutorial on the universality and expressiveness on fold chapter 4.1.
Here is first attempt at it
simpleRecursive f v xs = fst $ foldr g (v,[]) xs
where
g x (acc, xs) = (f x xs acc,x:xs)
However, above definition does not halt for head $ simpleRecursive (\x xs acc -> x:xs) [] [1..]
Below is definition that halt
simpleRecursive f v xs = fst $ foldr g (v,[]) xs
where
g x r = let (acc,xs) = r
in (f x xs acc,x:xs)
Given almost similar definition but different result, why does it differ? Does it have to do with how Haskell pattern match?
The crucial difference between the two functions is that in
g x r = let (acc, xs) = r
in (f x xs acc, x:xs)
The pattern match on the tuple constructor is irrefutable, whereas in
g x (acc, xs) = (f x xs acc, x:xs)
it is not. In other words, the first definition of g is equivalent to
g x ~(acc, xs) = (f x xs acc, x:xs)

Define functions with foldl foldr

I understand the definitions of foldl, foldr, but I have problems with functions defined by them.
For example map with foldr:
map f [] = []
map f l = foldr (\x xs -> f x : xs) [] l
I don't understand the (\x xs -> f x : xs). It is the map function, which foldr takes? But shouldn't it be (\x xs -> f x : f xs), because map f (x:xs) = f x : map f xs?
Example with foldl:
concat (x:xs) = x ++ concat xs
concat' xs = foldl (++) [] xs
concat'' xs = foldl (\ys y -> ys ++ y) [] xs
Of course I understand (++), but what's the logic behind (\ys y -> ys ++ y)? Is it ys = [] and y = xs?
So the function takes [] as ys and y is the first element of xs and concates the [] with the y?
Concrete example:
concat'' [1,2,3] = foldl (\ys y -> ys ++ y) [] [1,2,3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [] [1]) [2,3]
=> foldl (\ys y -> ys ++ y) [1] [2,3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1] [2]) [3]
=> foldl (\ys y -> ys ++ y) [1,2] [3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1,2] [3]) []
=> foldl (\ys y -> ys ++ y) [1,2,3] []
=> [1,2,3]
Another thing: concat only takes 1 list xs, so if I want to concat 2 lists?
concat (x:xs) ys = x ++ concat xs ys
concat [1,2,3] [4,5,6] with foldl?
Reverse:
reverse (x:xs) = reverse xs ++ [x]
reverse' l = foldl (\xs x -> [x] : xs) [] l
reverse'' l = foldr (\x xs -> xs ++ [x]) [] l
The foldr is intuitive clear (with the questions from above), but what's behind the reverse order in foldl (\xs x -> [x] : xs)? This foldl (\x xs -> xs ++ [x]) [] l would be wrong, wouldn't it?
Thanks a lot!
The code
foldr (\x xs -> ...) end list
could be read, roughly, as follows
scan the whole list
if it's empty, just return end end
otherwise:
let x be the element at hand
let xs be the rest of the list, after having been processed
apply the ... operation
The emphasized part is crucial. xs is not the rest of the list, but the result of the "recursive call" on it.
Indeed, xs is a bad name for that. In thee general case, it's not even a list! E.g. one would never write (silly example)
foldr (\x xs -> x + xs) 0 [1..100] -- sum 1..100
but rather prefer something like
foldr (\x partialSum -> x + partialSum) 0 [1..100] -- sum 1..100
(Actually, one would not sum using foldr, but let's leave that aside.)
So, just read it like this:
map f l = foldr (\x mappedTail -> f x : mappedTail) [] l

Resources