Hello I have two versions of this function and I am having some trouble.
iter :: Int -> (a -> a) -> (a -> a)
iter n f
| n > 0 = f . iter (n-1) f
| otherwise = id
iter' :: Int -> (a -> a) -> (a -> a)
iter' n = foldr (.) id . replicate n
I cannot understand even after googling what does id actually do here.
Like for example if we come to the function with n = 3
and f x = x+1
.
When we iterate through the whole n
and come to the point when id
is being called what happens with our variables?
I am very big newbie so could you please explain as simplistically as possible.
Summing a list xs = [x1,x2,...,xn]
can be visualized as
x1 + x2 + ... + xn + 0
Note that + 0
at the very end. Its purpose is to handle the case where the list is empty, i.e. xs = []
and n=0
. In such case the sum above reduces to 0
, which is the correct sum for an empty list.
Also note that when the list is not empty the extra + 0
has no impact ont the sum, so it's harmless. We indeed choose 0
since it is the neutral element for addition: x + 0 = x
for all x
.
If we want to compute a product, we would write
x1 * x2 * ... * xn * 1
Note that * 1
at the end. Its role is exactly the same as the + 0
seen above. Also note that 1
is the neutral element of multiplication: x * 1 = x
for all x
.
If we want to compute the composition of a list of functions, we would write
f1 . f2 . ... . fn . id
Note that . id
at the end. Its role is exactly the same as the + 0
and * 1
seen above. Also note that id
is the neutral element of composition f . id = f
for all f
.
Hopefully this will help you understand why, every time we compute a fold like
x1 op x2 op ... op xn
where op
is any binary operation, we want to end with ... op neutral_element
so to handle the empty list case, and still act as a good base case for non-empty lists.