If you are interested in delving deeper into theory, I suggest you read something about catamorphisms , anamorphisms, and hylomorphisms . Although the category theory surrounding it may seem a little intimidating, the concept is not so difficult.
Catamorphisms are functions that consume recursive data structures and produce some kind of value. Anamorphisms are functions that, with a certain value (type of seed), create recursive data structures. In particular, foldr and build , mentioned in other anniversaries, are functions for constructing catamorphisms and anamorphisms in lists. But this concept can be applied to almost any recursive data structure, for example, to various types of trees, etc.
Now, if you create a recursive data structure with anamorphism, and then destroy it with a catamorphism, you get the so-called hilomorphism. In this case, you actually do not need an intermediate structure. You can skip its creation and destroy. This is often called a deforestation .
Regarding map : this function is interesting in that it is both a catamorphism and anamorphism:
map consumes a list and produces something; but alsomap creates a list, consumes something.
Thus, you can consider the composition of two maps map f . map g map f . map g as a composition of anamorphism ( map g ) with a catamorphism ( map f ), forming a hilomorphism. Thus, you know that you can optimize (deforestation) without creating an interim list.
Specifically: you can write map two ways: using foldr , and the other using build :
mapAna :: (a -> b) -> [a] -> [b] mapAna f xs = build (mapAna' f xs) mapAna' :: (a -> b) -> [a] -> (b -> c -> c) -> c -> c mapAna' f [] cons nil = nil mapAna' f (x : xs) cons nil = (fx) `cons` (mapAna' f xs cons nil) mapCata :: (a -> b) -> [a] -> [b] mapCata f xs = foldr (\x ys -> fx : ys) [] xs
and the composition of map f (map g zs) as mapCata f (mapAna g zs) , which after some simplifications and application of foldr cn (build g) == gcn leads to map (f . g) .
Petr pudlák
source share