the foldr function:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr func acc [] = acc
foldr func acc (x:xs) = func x (foldr func acc xs)
catches patterns like those (left side) and makes them simpler (right side)
sum :: [Integer] -> Integer | sum :: [Integer] -> Integer
sum [] = 0 | sum [] = 0
sum (x:xs) = x + sum xs | sum (x:xs) = foldr (+) 0 xs
|
product :: [Integer] -> Integer | product :: [Integer] -> Integer
product [] = 0 | product [] = 0
product (x:xs) = x * product xs | product (x:xs) = foldr (*) 1 xs
|
concat :: [[a]] -> [a] | concat :: [[a]] -> [a]
concat [] = [] | concat [] = []
concat (x:xs) = x ++ concat xs | concat (x:xs) = foldr (++) [] xs
----------------------------------------------------------------------
not using folds | using folds
one thing I noticed was that the acc argument, provided as input for the fold, seems to be exactly the neutral element / identity element of that function.
In Mathematics the neutral element of the addition operation + is 0
because n + 0 = n, n ∈ ℝ
it doesn't change anything, in other words: With this neutral element provided as an input for the addition function, the summand equals the sum.
(+) summand 0 = summand or summand + 0 = summand
The same goes for multiplication, the product of the factor and the identiy equals the factor itelf:
(*) factor 1 = factor
So is this just a coincidence or is there someting bigger behind ?
[]vs(x:xs)case distinction, only one clausesum xs = foldr (+) 0 xs. - leftaroundaboutfoldl'instead offoldr, but that's more of a performance detail.) - leftaroundaboutmemptyelement forProduct(that is, the identity argument for multiplication) is1, not0. - Yann Vernier