Catamorphism
Homomorphism from an initial algebra into another algebra
- 19 min read
- 3 chapters
Related on Lably
Through Category (mathematics) and Natural number
Catamorphisms provide generalizations of folds of lists to arbitrary algebraic data types, which can be described as initial algebras. The dual concept is that of anamorphism that generalize unfolds. A hylomorphism is the composition of an anamorphism followed by a catamorphism.
Definition
Consider an initial -algebra for some endofunctor of some category into itself. Here is a morphism from to . Since it is initial, we know that whenever is another -algebra, i.e. a morphism from to , there is a unique homomorphism from to . By the definition of the category of -algebra, this corresponds to a morphism from to , conventionally also denoted , such that . In the context of -algebra, the uniquely specified morphism from the initial object is denoted by and hence characterized by the following relationship:
Sign in to keep reading
2 more chapters are free with a Lably account.
Terminology and history
Another notation found in the literature is . The open brackets used are known as banana brackets, after which catamorphisms are sometimes referred to as bananas, as mentioned in Erik Meijer et al. One of the first publications to introduce the notion of a catamorphism in the context of programming was the paper “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”, by Erik Meijer et al., which was in the context of the Squiggol formalism. The general categorical definition was given by Grant Malcolm.
Examples
We give a series of examples, and then a more global approach to catamorphisms, in the Haskell programming language.
Catamorphism for Maybe-algebra
Consider the functor Maybe defined in the below Haskell code:
<span id="mwXg"></span><span class="kr" id="mwXw">data</span><span class="w" id="mwYA"> </span><span class="kt" id="mwYQ">Maybe</span><span class="w" id="mwYg"> </span><span class="n" id="mwYw">a</span><span class="w" id="mwZA"> </span><span class="ow" id="mwZQ">=</span><span class="w" id="mwZg"> </span><span class="kt" id="mwZw">Nothing</span><span class="w" id="mwaA"> </span><span class="o" id="mwaQ">|</span><span class="w" id="mwag"> </span><span class="kt" id="mwaw">Just</span><span class="w" id="mwbA"> </span><span class="n" id="mwbQ">a</span><span class="w" id="mwbg"> </span><span class="c1" id="mwbw">-- Maybe type</span> <span class="kr" id="mwcA">class</span><span class="w" id="mwcQ"> </span><span class="kt" id="mwcg">Functor</span><span class="w" id="mwcw"> </span><span class="n" id="mwdA">f</span><span class="w" id="mwdQ"> </span><span class="kr" id="mwdg">where</span><span class="w" id="mwdw"> </span><span class="c1" id="mweA">-- class for functors</span> <span class="w" id="mweQ"> </span><span class="n" id="mweg">fmap</span><span class="w" id="mwew"> </span><span class="ow" id="mwfA">::</span><span class="w" id="mwfQ"> </span><span class="p" id="mwfg">(</span><span class="n" id="mwfw">a</span><span class="w" id="mwgA"> </span><span class="ow" id="mwgQ">-></span><span class="w" id="mwgg"> </span><span class="n" id="mwgw">b</span><span class="p" id="mwhA">)</span><span class="w" id="mwhQ"> </span><span class="ow" id="mwhg">-></span><span class="w" id="mwhw"> </span><span class="p" id="mwiA">(</span><span class="n" id="mwiQ">f</span><span class="w" id="mwig"> </span><span class="n" id="mwiw">a</span><span class="w" id="mwjA"> </span><span class="ow" id="mwjQ">-></span><span class="w" id="mwjg"> </span><span class="n" id="mwjw">f</span><span class="w" id="mwkA"> </span><span class="n" id="mwkQ">b</span><span class="p" id="mwkg">)</span><span class="w" id="mwkw"> </span><span class="c1" id="mwlA">-- action of functor on morphisms</span> <span class="kr" id="mwlQ">instance</span><span class="w" id="mwlg"> </span><span class="kt" id="mwlw">Functor</span><span class="w" id="mwmA"> </span><span class="kt" id="mwmQ">Maybe</span><span class="w" id="mwmg"> </span><span class="kr" id="mwmw">where</span><span class="w" id="mwnA"> </span><span class="c1" id="mwnQ">-- turn Maybe into a functor</span> <span class="w" id="mwng"> </span><span class="n" id="mwnw">fmap</span><span class="w" id="mwoA"> </span><span class="n" id="mwoQ">g</span><span class="w" id="mwog"> </span><span class="kt" id="mwow">Nothing</span><span class="w" id="mwpA"> </span><span class="ow" id="mwpQ">=</span><span class="w" id="mwpg"> </span><span class="kt" id="mwpw">Nothing</span> <span class="w" id="mwqA"> </span><span class="n" id="mwqQ">fmap</span><span class="w" id="mwqg"> </span><span class="n" id="mwqw">g</span><span class="w" id="mwrA"> </span><span class="p" id="mwrQ">(</span><span class="kt" id="mwrg">Just</span><span class="w" id="mwrw"> </span><span class="n" id="mwsA">x</span><span class="p" id="mwsQ">)</span><span class="w" id="mwsg"> </span><span class="ow" id="mwsw">=</span><span class="w" id="mwtA"> </span><span class="kt" id="mwtQ">Just</span><span class="w" id="mwtg"> </span><span class="p" id="mwtw">(</span><span class="n" id="mwuA">g</span><span class="w" id="mwuQ"> </span><span class="n" id="mwug">x</span><span class="p" id="mwuw">)</span>
The initial object of the Maybe-Algebra is the set of all objects of natural number type Nat together with the morphism ini defined below:
<span id="mwyg"></span><span class="kr" id="mwyw">data</span><span class="w" id="mwzA"> </span><span class="kt" id="mwzQ">Nat</span><span class="w" id="mwzg"> </span><span class="ow" id="mwzw">=</span><span class="w" id="mw0A"> </span><span class="kt" id="mw0Q">Zero</span><span class="w" id="mw0g"> </span><span class="o" id="mw0w">|</span><span class="w" id="mw1A"> </span><span class="kt" id="mw1Q">Succ</span><span class="w" id="mw1g"> </span><span class="kt" id="mw1w">Nat</span><span class="w" id="mw2A"> </span><span class="c1" id="mw2Q">-- natural number type</span> <span class="nf" id="mw2g">ini</span><span class="w" id="mw2w"> </span><span class="ow" id="mw3A">::</span><span class="w" id="mw3Q"> </span><span class="kt" id="mw3g">Maybe</span><span class="w" id="mw3w"> </span><span class="kt" id="mw4A">Nat</span><span class="w" id="mw4Q"> </span><span class="ow" id="mw4g">-></span><span class="w" id="mw4w"> </span><span class="kt" id="mw5A">Nat</span><span class="w" id="mw5Q"> </span><span class="c1" id="mw5g">-- initial object of Maybe-algebra (with slight abuse of notation) </span> <span class="nf" id="mw5w">ini</span><span class="w" id="mw6A"> </span><span class="kt" id="mw6Q">Nothing</span><span class="w" id="mw6g"> </span><span class="ow" id="mw6w">=</span><span class="w" id="mw7A"> </span><span class="kt" id="mw7Q">Zero</span> <span class="nf" id="mw7g">ini</span><span class="w" id="mw7w"> </span><span class="p" id="mw8A">(</span><span class="kt" id="mw8Q">Just</span><span class="w" id="mw8g"> </span><span class="n" id="mw8w">n</span><span class="p" id="mw9A">)</span><span class="w" id="mw9Q"> </span><span class="ow" id="mw9g">=</span><span class="w" id="mw9w"> </span><span class="kt" id="mw-A">Succ</span><span class="w" id="mw-Q"> </span><span class="n" id="mw-g">n</span>
The cata map can be defined as follows:
<span id="mwAQM"></span><span class="nf" id="mwAQQ">cata</span><span class="w" id="mwAQU"> </span><span class="ow" id="mwAQY">::</span><span class="w" id="mwAQc"> </span><span class="p" id="mwAQg">(</span><span class="kt" id="mwAQk">Maybe</span><span class="w" id="mwAQo"> </span><span class="n" id="mwAQs">b</span><span class="w" id="mwAQw"> </span><span class="ow" id="mwAQ0">-></span><span class="w" id="mwAQ4"> </span><span class="n" id="mwAQ8">b</span><span class="p" id="mwARA">)</span><span class="w" id="mwARE"> </span><span class="ow" id="mwARI">-></span><span class="w" id="mwARM"> </span><span class="p" id="mwARQ">(</span><span class="kt" id="mwARU">Nat</span><span class="w" id="mwARY"> </span><span class="ow" id="mwARc">-></span><span class="w" id="mwARg"> </span><span class="n" id="mwARk">b</span><span class="p" id="mwARo">)</span> <span class="nf" id="mwARs">cata</span><span class="w" id="mwARw"> </span><span class="n" id="mwAR0">g</span><span class="w" id="mwAR4"> </span><span class="kt" id="mwAR8">Zero</span><span class="w" id="mwASA"> </span><span class="ow" id="mwASE">=</span><span class="w" id="mwASI"> </span><span class="n" id="mwASM">g</span><span class="w" id="mwASQ"> </span><span class="p" id="mwASU">(</span><span class="n" id="mwASY">fmap</span><span class="w" id="mwASc"> </span><span class="p" id="mwASg">(</span><span class="n" id="mwASk">cata</span><span class="w" id="mwASo"> </span><span class="n" id="mwASs">g</span><span class="p" id="mwASw">)</span><span class="w" id="mwAS0"> </span><span class="kt" id="mwAS4">Nothing</span><span class="p" id="mwAS8">)</span><span class="w" id="mwATA"> </span><span class="c1" id="mwATE">-- Notice: fmap (cata g) Nothing = Nothing and Zero = ini(Nothing)</span> <span class="nf" id="mwATI">cata</span><span class="w" id="mwATM"> </span><span class="n" id="mwATQ">g</span><span class="w" id="mwATU"> </span><span class="p" id="mwATY">(</span><span class="kt" id="mwATc">Succ</span><span class="w" id="mwATg"> </span><span class="n" id="mwATk">n</span><span class="p" id="mwATo">)</span><span class="w" id="mwATs"> </span><span class="ow" id="mwATw">=</span><span class="w" id="mwAT0"> </span><span class="n" id="mwAT4">g</span><span class="w" id="mwAT8"> </span><span class="p" id="mwAUA">(</span><span class="n" id="mwAUE">fmap</span><span class="w" id="mwAUI"> </span><span class="p" id="mwAUM">(</span><span class="n" id="mwAUQ">cata</span><span class="w" id="mwAUU"> </span><span class="n" id="mwAUY">g</span><span class="p" id="mwAUc">)</span><span class="w" id="mwAUg"> </span><span class="p" id="mwAUk">(</span><span class="kt" id="mwAUo">Just</span><span class="w" id="mwAUs"> </span><span class="n" id="mwAUw">n</span><span class="p" id="mwAU0">))</span><span class="w" id="mwAU4"> </span><span class="c1" id="mwAU8">-- Notice: fmap (cata g) (Just n) = Just (cata g n) and Succ n = ini(Just n)</span>
As an example consider the following morphism:
<span id="mwAVM"></span><span class="nf" id="mwAVQ">g</span><span class="w" id="mwAVU"> </span><span class="ow" id="mwAVY">::</span><span class="w" id="mwAVc"> </span><span class="kt" id="mwAVg">Maybe</span><span class="w" id="mwAVk"> </span><span class="kt" id="mwAVo">String</span><span class="w" id="mwAVs"> </span><span class="ow" id="mwAVw">-></span><span class="w" id="mwAV0"> </span><span class="kt" id="mwAV4">String</span><span class="w" id="mwAV8"> </span> <span class="nf" id="mwAWA">g</span><span class="w" id="mwAWE"> </span><span class="kt" id="mwAWI">Nothing</span><span class="w" id="mwAWM"> </span><span class="ow" id="mwAWQ">=</span><span class="w" id="mwAWU"> </span><span class="s" id="mwAWY">"go!"</span> <span class="nf" id="mwAWc">g</span><span class="w" id="mwAWg"> </span><span class="p" id="mwAWk">(</span><span class="kt" id="mwAWo">Just</span><span class="w" id="mwAWs"> </span><span class="n" id="mwAWw">str</span><span class="p" id="mwAW0">)</span><span class="w" id="mwAW4"> </span><span class="ow" id="mwAW8">=</span><span class="w" id="mwAXA"> </span><span class="s" id="mwAXE">"wait..."</span><span class="w" id="mwAXI"> </span><span class="o" id="mwAXM">++</span><span class="w" id="mwAXQ"> </span><span class="n" id="mwAXU">str</span>
Then cata g ((Succ. Succ . Succ) Zero) will evaluate to "wait... wait... wait... go!".
List fold
For a fixed type a consider the functor MaybeProd a defined by the following:
<span id="mwAX4"></span><span class="kr" id="mwAX8">data</span><span class="w" id="mwAYA"> </span><span class="kt" id="mwAYE">MaybeProd</span><span class="w" id="mwAYI"> </span><span class="n" id="mwAYM">a</span><span class="w" id="mwAYQ"> </span><span class="n" id="mwAYU">b</span><span class="w" id="mwAYY"> </span><span class="ow" id="mwAYc">=</span><span class="w" id="mwAYg"> </span><span class="kt" id="mwAYk">Nothing</span><span class="w" id="mwAYo"> </span><span class="o" id="mwAYs">|</span><span class="w" id="mwAYw"> </span><span class="kt" id="mwAY0">Just</span><span class="w" id="mwAY4"> </span><span class="p" id="mwAY8">(</span><span class="n" id="mwAZA">a</span><span class="p" id="mwAZE">,</span><span class="w" id="mwAZI"> </span><span class="n" id="mwAZM">b</span><span class="p" id="mwAZQ">)</span><span class="w" id="mwAZU"> </span><span class="c1" id="mwAZY">-- (a,b) is the product type of a and b</span> <span class="kr" id="mwAZc">class</span><span class="w" id="mwAZg"> </span><span class="kt" id="mwAZk">Functor</span><span class="w" id="mwAZo"> </span><span class="n" id="mwAZs">f</span><span class="w" id="mwAZw"> </span><span class="kr" id="mwAZ0">where</span><span class="w" id="mwAZ4"> </span><span class="c1" id="mwAZ8">-- class for functors</span> <span class="w" id="mwAaA"> </span><span class="n" id="mwAaE">fmap</span><span class="w" id="mwAaI"> </span><span class="ow" id="mwAaM">::</span><span class="w" id="mwAaQ"> </span><span class="p" id="mwAaU">(</span><span class="n" id="mwAaY">a</span><span class="w" id="mwAac"> </span><span class="ow" id="mwAag">-></span><span class="w" id="mwAak"> </span><span class="n" id="mwAao">b</span><span class="p" id="mwAas">)</span><span class="w" id="mwAaw"> </span><span class="ow" id="mwAa0">-></span><span class="w" id="mwAa4"> </span><span class="p" id="mwAa8">(</span><span class="n" id="mwAbA">f</span><span class="w" id="mwAbE"> </span><span class="n" id="mwAbI">a</span><span class="w" id="mwAbM"> </span><span class="ow" id="mwAbQ">-></span><span class="w" id="mwAbU"> </span><span class="n" id="mwAbY">f</span><span class="w" id="mwAbc"> </span><span class="n" id="mwAbg">b</span><span class="p" id="mwAbk">)</span><span class="w" id="mwAbo"> </span><span class="c1" id="mwAbs">-- action of functor on morphisms</span> <span class="kr" id="mwAbw">instance</span><span class="w" id="mwAb0"> </span><span class="kt" id="mwAb4">Functor</span><span class="w" id="mwAb8"> </span><span class="p" id="mwAcA">(</span><span class="kt" id="mwAcE">MaybeProd</span><span class="w" id="mwAcI"> </span><span class="n" id="mwAcM">a</span><span class="p" id="mwAcQ">)</span><span class="w" id="mwAcU"> </span><span class="kr" id="mwAcY">where</span><span class="w" id="mwAcc"> </span><span class="c1" id="mwAcg">-- turn MaybeProd a into a functor, the functoriality is only in the second type variable</span> <span class="w" id="mwAck"> </span><span class="n" id="mwAco">fmap</span><span class="w" id="mwAcs"> </span><span class="n" id="mwAcw">g</span><span class="w" id="mwAc0"> </span><span class="kt" id="mwAc4">Nothing</span><span class="w" id="mwAc8"> </span><span class="ow" id="mwAdA">=</span><span class="w" id="mwAdE"> </span><span class="kt" id="mwAdI">Nothing</span> <span class="w" id="mwAdM"> </span><span class="n" id="mwAdQ">fmap</span><span class="w" id="mwAdU"> </span><span class="n" id="mwAdY">g</span><span class="w" id="mwAdc"> </span><span class="p" id="mwAdg">(</span><span class="kt" id="mwAdk">Just</span><span class="w" id="mwAdo"> </span><span class="p" id="mwAds">(</span><span class="n" id="mwAdw">x</span><span class="p" id="mwAd0">,</span><span class="n" id="mwAd4">y</span><span class="p" id="mwAd8">))</span><span class="w" id="mwAeA"> </span><span class="ow" id="mwAeE">=</span><span class="w" id="mwAeI"> </span><span class="kt" id="mwAeM">Just</span><span class="w" id="mwAeQ"> </span><span class="p" id="mwAeU">(</span><span class="n" id="mwAeY">x</span><span class="p" id="mwAec">,</span><span class="w" id="mwAeg"> </span><span class="n" id="mwAek">g</span><span class="w" id="mwAeo"> </span><span class="n" id="mwAes">y</span><span class="p" id="mwAew">)</span>
The initial algebra of MaybeProd a is given by the lists of elements with type a together with the morphism ini defined below:
<span id="mwAfc"></span><span class="kr" id="mwAfg">data</span><span class="w" id="mwAfk"> </span><span class="kt" id="mwAfo">List</span><span class="w" id="mwAfs"> </span><span class="n" id="mwAfw">a</span><span class="w" id="mwAf0"> </span><span class="ow" id="mwAf4">=</span><span class="w" id="mwAf8"> </span><span class="kt" id="mwAgA">EmptyList</span><span class="w" id="mwAgE"> </span><span class="o" id="mwAgI">|</span><span class="w" id="mwAgM"> </span><span class="kt" id="mwAgQ">Cons</span><span class="w" id="mwAgU"> </span><span class="n" id="mwAgY">a</span><span class="w" id="mwAgc"> </span><span class="p" id="mwAgg">(</span><span class="kt" id="mwAgk">List</span><span class="w" id="mwAgo"> </span><span class="n" id="mwAgs">a</span><span class="p" id="mwAgw">)</span> <span class="nf" id="mwAg0">ini</span><span class="w" id="mwAg4"> </span><span class="ow" id="mwAg8">::</span><span class="w" id="mwAhA"> </span><span class="kt" id="mwAhE">MaybeProd</span><span class="w" id="mwAhI"> </span><span class="n" id="mwAhM">a</span><span class="w" id="mwAhQ"> </span><span class="p" id="mwAhU">(</span><span class="kt" id="mwAhY">List</span><span class="w" id="mwAhc"> </span><span class="n" id="mwAhg">a</span><span class="p" id="mwAhk">)</span><span class="w" id="mwAho"> </span><span class="ow" id="mwAhs">-></span><span class="w" id="mwAhw"> </span><span class="kt" id="mwAh0">List</span><span class="w" id="mwAh4"> </span><span class="n" id="mwAh8">a</span><span class="w" id="mwAiA"> </span><span class="c1" id="mwAiE">-- initial algebra of MaybeProd a</span> <span class="nf" id="mwAiI">ini</span><span class="w" id="mwAiM"> </span><span class="kt" id="mwAiQ">Nothing</span><span class="w" id="mwAiU"> </span><span class="ow" id="mwAiY">=</span><span class="w" id="mwAic"> </span><span class="kt" id="mwAig">EmptyList</span> <span class="nf" id="mwAik">ini</span><span class="w" id="mwAio"> </span><span class="p" id="mwAis">(</span><span class="kt" id="mwAiw">Just</span><span class="w" id="mwAi0"> </span><span class="p" id="mwAi4">(</span><span class="n" id="mwAi8">n</span><span class="p" id="mwAjA">,</span><span class="n" id="mwAjE">l</span><span class="p" id="mwAjI">))</span><span class="w" id="mwAjM"> </span><span class="ow" id="mwAjQ">=</span><span class="w" id="mwAjU"> </span><span class="kt" id="mwAjY">Cons</span><span class="w" id="mwAjc"> </span><span class="n" id="mwAjg">n</span><span class="w" id="mwAjk"> </span><span class="n" id="mwAjo">l</span>
The cata map can be defined by:
<span id="mwAj8"></span><span class="nf" id="mwAkA">cata</span><span class="w" id="mwAkE"> </span><span class="ow" id="mwAkI">::</span><span class="w" id="mwAkM"> </span><span class="p" id="mwAkQ">(</span><span class="kt" id="mwAkU">MaybeProd</span><span class="w" id="mwAkY"> </span><span class="n" id="mwAkc">a</span><span class="w" id="mwAkg"> </span><span class="n" id="mwAkk">b</span><span class="w" id="mwAko"> </span><span class="ow" id="mwAks">-></span><span class="w" id="mwAkw"> </span><span class="n" id="mwAk0">b</span><span class="p" id="mwAk4">)</span><span class="w" id="mwAk8"> </span><span class="ow" id="mwAlA">-></span><span class="w" id="mwAlE"> </span><span class="p" id="mwAlI">(</span><span class="kt" id="mwAlM">List</span><span class="w" id="mwAlQ"> </span><span class="n" id="mwAlU">a</span><span class="w" id="mwAlY"> </span><span class="ow" id="mwAlc">-></span><span class="w" id="mwAlg"> </span><span class="n" id="mwAlk">b</span><span class="p" id="mwAlo">)</span> <span class="nf" id="mwAls">cata</span><span class="w" id="mwAlw"> </span><span class="n" id="mwAl0">g</span><span class="w" id="mwAl4"> </span><span class="kt" id="mwAl8">EmptyList</span><span class="w" id="mwAmA"> </span><span class="ow" id="mwAmE">=</span><span class="w" id="mwAmI"> </span><span class="n" id="mwAmM">g</span><span class="w" id="mwAmQ"> </span><span class="p" id="mwAmU">(</span><span class="n" id="mwAmY">fmap</span><span class="w" id="mwAmc"> </span><span class="p" id="mwAmg">(</span><span class="n" id="mwAmk">cata</span><span class="w" id="mwAmo"> </span><span class="n" id="mwAms">g</span><span class="p" id="mwAmw">)</span><span class="w" id="mwAm0"> </span><span class="kt" id="mwAm4">Nothing</span><span class="p" id="mwAm8">)</span><span class="w" id="mwAnA"> </span><span class="c1" id="mwAnE">-- Note: ini Nothing = EmptyList</span> <span class="nf" id="mwAnI">cata</span><span class="w" id="mwAnM"> </span><span class="n" id="mwAnQ">g</span><span class="w" id="mwAnU"> </span><span class="p" id="mwAnY">(</span><span class="kt" id="mwAnc">Cons</span><span class="w" id="mwAng"> </span><span class="n" id="mwAnk">s</span><span class="w" id="mwAno"> </span><span class="n" id="mwAns">l</span><span class="p" id="mwAnw">)</span><span class="w" id="mwAn0"> </span><span class="ow" id="mwAn4">=</span><span class="w" id="mwAn8"> </span><span class="n" id="mwAoA">g</span><span class="w" id="mwAoE"> </span><span class="p" id="mwAoI">(</span><span class="n" id="mwAoM">fmap</span><span class="w" id="mwAoQ"> </span><span class="p" id="mwAoU">(</span><span class="n" id="mwAoY">cata</span><span class="w" id="mwAoc"> </span><span class="n" id="mwAog">g</span><span class="p" id="mwAok">)</span><span class="w" id="mwAoo"> </span><span class="p" id="mwAos">(</span><span class="kt" id="mwAow">Just</span><span class="w" id="mwAo0"> </span><span class="p" id="mwAo4">(</span><span class="n" id="mwAo8">s</span><span class="p" id="mwApA">,</span><span class="n" id="mwApE">l</span><span class="p" id="mwApI">)))</span><span class="w" id="mwApM"> </span><span class="c1" id="mwApQ">-- Note: Cons s l = ini (Just (s,l))</span>
Notice also that cata g (Cons s l) = g (Just (s, cata g l)). As an example consider the following morphism:
<span id="mwApk"></span><span class="nf" id="mwApo">g</span><span class="w" id="mwAps"> </span><span class="ow" id="mwApw">::</span><span class="w" id="mwAp0"> </span><span class="kt" id="mwAp4">MaybeProd</span><span class="w" id="mwAp8"> </span><span class="kt" id="mwAqA">Int</span><span class="w" id="mwAqE"> </span><span class="kt" id="mwAqI">Int</span><span class="w" id="mwAqM"> </span><span class="ow" id="mwAqQ">-></span><span class="w" id="mwAqU"> </span><span class="kt" id="mwAqY">Int</span> <span class="nf" id="mwAqc">g</span><span class="w" id="mwAqg"> </span><span class="kt" id="mwAqk">Nothing</span><span class="w" id="mwAqo"> </span><span class="ow" id="mwAqs">=</span><span class="w" id="mwAqw"> </span><span class="mi" id="mwAq0">3</span> <span class="nf" id="mwAq4">g</span><span class="w" id="mwAq8"> </span><span class="p" id="mwArA">(</span><span class="kt" id="mwArE">Just</span><span class="w" id="mwArI"> </span><span class="p" id="mwArM">(</span><span class="n" id="mwArQ">x</span><span class="p" id="mwArU">,</span><span class="n" id="mwArY">y</span><span class="p" id="mwArc">))</span><span class="w" id="mwArg"> </span><span class="ow" id="mwArk">=</span><span class="w" id="mwAro"> </span><span class="n" id="mwArs">x</span><span class="o" id="mwArw">*</span><span class="n" id="mwAr0">y</span>
cata g (Cons 10 EmptyList) evaluates to 30. This can be seen by expanding cata g (Cons 10 EmptyList) = g (Just (10,cata g EmptyList)) = 10*(cata g EmptyList) = 10*(g Nothing) = 10*3.
In the same way it can be shown, that cata g (Cons 10 (Cons 100 (Cons 1000 EmptyList))) will evaluate to 10*(100*(1000*3)) = 3.000.000.
The cata map is closely related to the right fold (see Fold (higher-order function)) of lists foldrList. The morphism lift defined by
<span id="mwAso"></span><span class="nf" id="mwAss">lift</span><span class="w" id="mwAsw"> </span><span class="ow" id="mwAs0">::</span><span class="w" id="mwAs4"> </span><span class="p" id="mwAs8">(</span><span class="n" id="mwAtA">a</span><span class="w" id="mwAtE"> </span><span class="ow" id="mwAtI">-></span><span class="w" id="mwAtM"> </span><span class="n" id="mwAtQ">b</span><span class="w" id="mwAtU"> </span><span class="ow" id="mwAtY">-></span><span class="w" id="mwAtc"> </span><span class="n" id="mwAtg">b</span><span class="p" id="mwAtk">)</span><span class="w" id="mwAto"> </span><span class="ow" id="mwAts">-></span><span class="w" id="mwAtw"> </span><span class="n" id="mwAt0">b</span><span class="w" id="mwAt4"> </span><span class="ow" id="mwAt8">-></span><span class="w" id="mwAuA"> </span><span class="p" id="mwAuE">(</span><span class="kt" id="mwAuI">MaybeProd</span><span class="w" id="mwAuM"> </span><span class="n" id="mwAuQ">a</span><span class="w" id="mwAuU"> </span><span class="n" id="mwAuY">b</span><span class="w" id="mwAuc"> </span><span class="ow" id="mwAug">-></span><span class="w" id="mwAuk"> </span><span class="n" id="mwAuo">b</span><span class="p" id="mwAus">)</span> <span class="nf" id="mwAuw">lift</span><span class="w" id="mwAu0"> </span><span class="n" id="mwAu4">g</span><span class="w" id="mwAu8"> </span><span class="n" id="mwAvA">b0</span><span class="w" id="mwAvE"> </span><span class="kt" id="mwAvI">Nothing</span><span class="w" id="mwAvM"> </span><span class="ow" id="mwAvQ">=</span><span class="w" id="mwAvU"> </span><span class="n" id="mwAvY">b0</span> <span class="nf" id="mwAvc">lift</span><span class="w" id="mwAvg"> </span><span class="n" id="mwAvk">g</span><span class="w" id="mwAvo"> </span><span class="n" id="mwAvs">b0</span><span class="w" id="mwAvw"> </span><span class="p" id="mwAv0">(</span><span class="kt" id="mwAv4">Just</span><span class="w" id="mwAv8"> </span><span class="p" id="mwAwA">(</span><span class="n" id="mwAwE">x</span><span class="p" id="mwAwI">,</span><span class="n" id="mwAwM">y</span><span class="p" id="mwAwQ">))</span><span class="w" id="mwAwU"> </span><span class="ow" id="mwAwY">=</span><span class="w" id="mwAwc"> </span><span class="n" id="mwAwg">g</span><span class="w" id="mwAwk"> </span><span class="n" id="mwAwo">x</span><span class="w" id="mwAws"> </span><span class="n" id="mwAww">y</span>
relates cata to the right fold foldrList of lists via:
<span id="mwAxI"></span><span class="nf" id="mwAxM">foldrList</span><span class="w" id="mwAxQ"> </span><span class="ow" id="mwAxU">::</span><span class="w" id="mwAxY"> </span><span class="p" id="mwAxc">(</span><span class="n" id="mwAxg">a</span><span class="w" id="mwAxk"> </span><span class="ow" id="mwAxo">-></span><span class="w" id="mwAxs"> </span><span class="n" id="mwAxw">b</span><span class="w" id="mwAx0"> </span><span class="ow" id="mwAx4">-></span><span class="w" id="mwAx8"> </span><span class="n" id="mwAyA">b</span><span class="p" id="mwAyE">)</span><span class="w" id="mwAyI"> </span><span class="ow" id="mwAyM">-></span><span class="w" id="mwAyQ"> </span><span class="n" id="mwAyU">b</span><span class="ow" id="mwAyY">-></span><span class="w" id="mwAyc"> </span><span class="kt" id="mwAyg">List</span><span class="w" id="mwAyk"> </span><span class="n" id="mwAyo">a</span><span class="w" id="mwAys"> </span><span class="ow" id="mwAyw">-></span><span class="w" id="mwAy0"> </span><span class="n" id="mwAy4">b</span> <span class="nf" id="mwAy8">foldrList</span><span class="w" id="mwAzA"> </span><span class="n" id="mwAzE">fun</span><span class="w" id="mwAzI"> </span><span class="n" id="mwAzM">b0</span><span class="w" id="mwAzQ"> </span><span class="ow" id="mwAzU">=</span><span class="w" id="mwAzY"> </span><span class="n" id="mwAzc">cata</span><span class="w" id="mwAzg"> </span><span class="p" id="mwAzk">(</span><span class="n" id="mwAzo">lift</span><span class="w" id="mwAzs"> </span><span class="n" id="mwAzw">fun</span><span class="w" id="mwAz0"> </span><span class="n" id="mwAz4">b0</span><span class="p" id="mwAz8">)</span>
The definition of cata implies, that foldrList is the right fold and not the left fold. As an example: foldrList (+) 1 (Cons 10 (Cons 100 (Cons 1000 EmptyList))) will evaluate to 1111 and foldrList (*) 3 (Cons 10 (Cons 100 (Cons 1000 EmptyList)) to 3.000.000.
Tree fold
For a fixed type a, consider the functor mapping types b to a type that contains a copy of each term of a as well as all pairs of b's (terms of the product type of two instances of the type b). An algebra consists of a function to b, which either acts on an a term or two b terms. This merging of a pair can be encoded as two functions of type a -> b resp. b -> b -> b.
<span id="mwA1Q"></span><span class="kr" id="mwA1U">type</span><span class="w" id="mwA1Y"> </span><span class="kt" id="mwA1c">TreeAlgebra</span><span class="w" id="mwA1g"> </span><span class="n" id="mwA1k">a</span><span class="w" id="mwA1o"> </span><span class="n" id="mwA1s">b</span><span class="w" id="mwA1w"> </span><span class="ow" id="mwA10">=</span><span class="w" id="mwA14"> </span><span class="p" id="mwA18">(</span><span class="n" id="mwA2A">a</span><span class="w" id="mwA2E"> </span><span class="ow" id="mwA2I">-></span><span class="w" id="mwA2M"> </span><span class="n" id="mwA2Q">b</span><span class="p" id="mwA2U">,</span><span class="w" id="mwA2Y"> </span><span class="n" id="mwA2c">b</span><span class="w" id="mwA2g"> </span><span class="ow" id="mwA2k">-></span><span class="w" id="mwA2o"> </span><span class="n" id="mwA2s">b</span><span class="w" id="mwA2w"> </span><span class="ow" id="mwA20">-></span><span class="w" id="mwA24"> </span><span class="n" id="mwA28">b</span><span class="p" id="mwA3A">)</span><span class="w" id="mwA3E"> </span><span class="c1" id="mwA3I">-- the "two cases" function is encoded as (f, g)</span> <span class="w" id="mwA3M"> </span> <span class="kr" id="mwA3Q">data</span><span class="w" id="mwA3U"> </span><span class="kt" id="mwA3Y">Tree</span><span class="w" id="mwA3c"> </span><span class="n" id="mwA3g">a</span><span class="w" id="mwA3k"> </span><span class="ow" id="mwA3o">=</span><span class="w" id="mwA3s"> </span><span class="kt" id="mwA3w">Leaf</span><span class="w" id="mwA30"> </span><span class="n" id="mwA34">a</span><span class="w" id="mwA38"> </span><span class="o" id="mwA4A">|</span><span class="w" id="mwA4E"> </span><span class="kt" id="mwA4I">Branch</span><span class="w" id="mwA4M"> </span><span class="p" id="mwA4Q">(</span><span class="kt" id="mwA4U">Tree</span><span class="w" id="mwA4Y"> </span><span class="n" id="mwA4c">a</span><span class="p" id="mwA4g">)</span><span class="w" id="mwA4k"> </span><span class="p" id="mwA4o">(</span><span class="kt" id="mwA4s">Tree</span><span class="w" id="mwA4w"> </span><span class="n" id="mwA40">a</span><span class="p" id="mwA44">)</span><span class="w" id="mwA48"> </span><span class="c1" id="mwA5A">-- which turns out to be the initial algebra</span> <span class="w" id="mwA5E"> </span> <span class="nf" id="mwA5I">foldTree</span><span class="w" id="mwA5M"> </span><span class="ow" id="mwA5Q">::</span><span class="w" id="mwA5U"> </span><span class="kt" id="mwA5Y">TreeAlgebra</span><span class="w" id="mwA5c"> </span><span class="n" id="mwA5g">a</span><span class="w" id="mwA5k"> </span><span class="n" id="mwA5o">b</span><span class="w" id="mwA5s"> </span><span class="ow" id="mwA5w">-></span><span class="w" id="mwA50"> </span><span class="p" id="mwA54">(</span><span class="kt" id="mwA58">Tree</span><span class="w" id="mwA6A"> </span><span class="n" id="mwA6E">a</span><span class="w" id="mwA6I"> </span><span class="ow" id="mwA6M">-></span><span class="w" id="mwA6Q"> </span><span class="n" id="mwA6U">b</span><span class="p" id="mwA6Y">)</span><span class="w" id="mwA6c"> </span><span class="c1" id="mwA6g">-- catamorphisms map from (Tree a) to b</span> <span class="nf" id="mwA6k">foldTree</span><span class="w" id="mwA6o"> </span><span class="p" id="mwA6s">(</span><span class="n" id="mwA6w">f</span><span class="p" id="mwA60">,</span><span class="w" id="mwA64"> </span><span class="n" id="mwA68">g</span><span class="p" id="mwA7A">)</span><span class="w" id="mwA7E"> </span><span class="p" id="mwA7I">(</span><span class="kt" id="mwA7M">Leaf</span><span class="w" id="mwA7Q"> </span><span class="n" id="mwA7U">x</span><span class="p" id="mwA7Y">)</span><span class="w" id="mwA7c"> </span><span class="ow" id="mwA7g">=</span><span class="w" id="mwA7k"> </span><span class="n" id="mwA7o">f</span><span class="w" id="mwA7s"> </span><span class="n" id="mwA7w">x</span> <span class="nf" id="mwA70">foldTree</span><span class="w" id="mwA74"> </span><span class="p" id="mwA78">(</span><span class="n" id="mwA8A">f</span><span class="p" id="mwA8E">,</span><span class="w" id="mwA8I"> </span><span class="n" id="mwA8M">g</span><span class="p" id="mwA8Q">)</span><span class="w" id="mwA8U"> </span><span class="p" id="mwA8Y">(</span><span class="kt" id="mwA8c">Branch</span><span class="w" id="mwA8g"> </span><span class="n" id="mwA8k">left</span><span class="w" id="mwA8o"> </span><span class="n" id="mwA8s">right</span><span class="p" id="mwA8w">)</span><span class="w" id="mwA80"> </span><span class="ow" id="mwA84">=</span><span class="w" id="mwA88"> </span><span class="n" id="mwA9A">g</span><span class="w" id="mwA9E"> </span><span class="p" id="mwA9I">(</span><span class="n" id="mwA9M">foldTree</span><span class="w" id="mwA9Q"> </span><span class="p" id="mwA9U">(</span><span class="n" id="mwA9Y">f</span><span class="p" id="mwA9c">,</span><span class="w" id="mwA9g"> </span><span class="n" id="mwA9k">g</span><span class="p" id="mwA9o">)</span><span class="w" id="mwA9s"> </span><span class="n" id="mwA9w">left</span><span class="p" id="mwA90">)</span><span class="w" id="mwA94"> </span><span class="p" id="mwA98">(</span><span class="n" id="mwA-A">foldTree</span><span class="w" id="mwA-E"> </span><span class="p" id="mwA-I">(</span><span class="n" id="mwA-M">f</span><span class="p" id="mwA-Q">,</span><span class="w" id="mwA-U"> </span><span class="n" id="mwA-Y">g</span><span class="p" id="mwA-c">)</span><span class="w" id="mwA-g"> </span><span class="n" id="mwA-k">right</span><span class="p" id="mwA-o">)</span>
<span id="mwA-0"></span><span class="nf" id="mwA-4">treeDepth</span><span class="w" id="mwA-8"> </span><span class="ow" id="mwA_A">::</span><span class="w" id="mwA_E"> </span><span class="kt" id="mwA_I">TreeAlgebra</span><span class="w" id="mwA_M"> </span><span class="n" id="mwA_Q">a</span><span class="w" id="mwA_U"> </span><span class="kt" id="mwA_Y">Integer</span><span class="w" id="mwA_c"> </span><span class="c1" id="mwA_g">-- an f-algebra to numbers, which works for any input type</span> <span class="nf" id="mwA_k">treeDepth</span><span class="w" id="mwA_o"> </span><span class="ow" id="mwA_s">=</span><span class="w" id="mwA_w"> </span><span class="p" id="mwA_0">(</span><span class="n" id="mwA_4">const</span><span class="w" id="mwA_8"> </span><span class="mi" id="mwBAA">1</span><span class="p" id="mwBAE">,</span><span class="w" id="mwBAI"> </span><span class="nf" id="mwBAM">\</span><span class="n" id="mwBAQ">i</span><span class="w" id="mwBAU"> </span><span class="n" id="mwBAY">j</span><span class="w" id="mwBAc"> </span><span class="ow" id="mwBAg">-></span><span class="w" id="mwBAk"> </span><span class="mi" id="mwBAo">1</span><span class="w" id="mwBAs"> </span><span class="o" id="mwBAw">+</span><span class="w" id="mwBA0"> </span><span class="n" id="mwBA4">max</span><span class="w" id="mwBA8"> </span><span class="n" id="mwBBA">i</span><span class="w" id="mwBBE"> </span><span class="n" id="mwBBI">j</span><span class="p" id="mwBBM">)</span> <span class="w" id="mwBBQ"> </span> <span class="nf" id="mwBBU">treeSum</span><span class="w" id="mwBBY"> </span><span class="ow" id="mwBBc">::</span><span class="w" id="mwBBg"> </span><span class="p" id="mwBBk">(</span><span class="kt" id="mwBBo">Num</span><span class="w" id="mwBBs"> </span><span class="n" id="mwBBw">a</span><span class="p" id="mwBB0">)</span><span class="w" id="mwBB4"> </span><span class="ow" id="mwBB8">=></span><span class="w" id="mwBCA"> </span><span class="kt" id="mwBCE">TreeAlgebra</span><span class="w" id="mwBCI"> </span><span class="n" id="mwBCM">a</span><span class="w" id="mwBCQ"> </span><span class="n" id="mwBCU">a</span><span class="w" id="mwBCY"> </span><span class="c1" id="mwBCc">-- an f-algebra, which works for any number type </span> <span class="nf" id="mwBCg">treeSum</span><span class="w" id="mwBCk"> </span><span class="ow" id="mwBCo">=</span><span class="w" id="mwBCs"> </span><span class="p" id="mwBCw">(</span><span class="n" id="mwBC0">id</span><span class="p" id="mwBC4">,</span><span class="w" id="mwBC8"> </span><span class="p" id="mwBDA">(</span><span class="o" id="mwBDE">+</span><span class="p" id="mwBDI">))</span>
General case
Deeper category theoretical studies of initial algebras reveal that the F-algebra obtained from applying the functor to its own initial algebra is isomorphic to it.
Strong type systems enable us to abstractly specify the initial algebra of a functor f as its fixed point a = f a. The recursively defined catamorphisms can now be coded in single line, where the case analysis (like in the different examples above) is encapsulated by the fmap. Since the domain of the latter are objects in the image of f, the evaluation of the catamorphisms jumps back and forth between a and f a.
<span id="mwBD0"></span><span class="kr" id="mwBD4">type</span><span class="w" id="mwBD8"> </span><span class="kt" id="mwBEA">Algebra</span><span class="w" id="mwBEE"> </span><span class="n" id="mwBEI">f</span><span class="w" id="mwBEM"> </span><span class="n" id="mwBEQ">a</span><span class="w" id="mwBEU"> </span><span class="ow" id="mwBEY">=</span><span class="w" id="mwBEc"> </span><span class="n" id="mwBEg">f</span><span class="w" id="mwBEk"> </span><span class="n" id="mwBEo">a</span><span class="w" id="mwBEs"> </span><span class="ow" id="mwBEw">-></span><span class="w" id="mwBE0"> </span><span class="n" id="mwBE4">a</span><span class="w" id="mwBE8"> </span><span class="c1" id="mwBFA">-- the generic f-algebras</span> <span class="kr" id="mwBFE">newtype</span><span class="w" id="mwBFI"> </span><span class="kt" id="mwBFM">Fix</span><span class="w" id="mwBFQ"> </span><span class="n" id="mwBFU">f</span><span class="w" id="mwBFY"> </span><span class="ow" id="mwBFc">=</span><span class="w" id="mwBFg"> </span><span class="kt" id="mwBFk">Iso</span><span class="w" id="mwBFo"> </span><span class="p" id="mwBFs">{</span><span class="w" id="mwBFw"> </span><span class="n" id="mwBF0">invIso</span><span class="w" id="mwBF4"> </span><span class="ow" id="mwBF8">::</span><span class="w" id="mwBGA"> </span><span class="n" id="mwBGE">f</span><span class="w" id="mwBGI"> </span><span class="p" id="mwBGM">(</span><span class="kt" id="mwBGQ">Fix</span><span class="w" id="mwBGU"> </span><span class="n" id="mwBGY">f</span><span class="p" id="mwBGc">)</span><span class="w" id="mwBGg"> </span><span class="p" id="mwBGk">}</span><span class="w" id="mwBGo"> </span><span class="c1" id="mwBGs">-- gives us the initial algebra for the functor f</span> <span class="nf" id="mwBGw">cata</span><span class="w" id="mwBG0"> </span><span class="ow" id="mwBG4">::</span><span class="w" id="mwBG8"> </span><span class="kt" id="mwBHA">Functor</span><span class="w" id="mwBHE"> </span><span class="n" id="mwBHI">f</span><span class="w" id="mwBHM"> </span><span class="ow" id="mwBHQ">=></span><span class="w" id="mwBHU"> </span><span class="kt" id="mwBHY">Algebra</span><span class="w" id="mwBHc"> </span><span class="n" id="mwBHg">f</span><span class="w" id="mwBHk"> </span><span class="n" id="mwBHo">a</span><span class="w" id="mwBHs"> </span><span class="ow" id="mwBHw">-></span><span class="w" id="mwBH0"> </span><span class="p" id="mwBH4">(</span><span class="kt" id="mwBH8">Fix</span><span class="w" id="mwBIA"> </span><span class="n" id="mwBIE">f</span><span class="w" id="mwBII"> </span><span class="ow" id="mwBIM">-></span><span class="w" id="mwBIQ"> </span><span class="n" id="mwBIU">a</span><span class="p" id="mwBIY">)</span><span class="w" id="mwBIc"> </span><span class="c1" id="mwBIg">-- catamorphism from Fix f to a</span> <span class="nf" id="mwBIk">cata</span><span class="w" id="mwBIo"> </span><span class="n" id="mwBIs">alg</span><span class="w" id="mwBIw"> </span><span class="ow" id="mwBI0">=</span><span class="w" id="mwBI4"> </span><span class="n" id="mwBI8">alg</span><span class="w" id="mwBJA"> </span><span class="o" id="mwBJE">.</span><span class="w" id="mwBJI"> </span><span class="n" id="mwBJM">fmap</span><span class="w" id="mwBJQ"> </span><span class="p" id="mwBJU">(</span><span class="n" id="mwBJY">cata</span><span class="w" id="mwBJc"> </span><span class="n" id="mwBJg">alg</span><span class="p" id="mwBJk">)</span><span class="w" id="mwBJo"> </span><span class="o" id="mwBJs">.</span><span class="w" id="mwBJw"> </span><span class="n" id="mwBJ0">invIso</span><span class="w" id="mwBJ4"> </span><span class="c1" id="mwBJ8">-- note that invIso and alg map in opposite directions</span>Now again the first example, but now via passing the Maybe functor to Fix. Repeated application of the Maybe functor generates a chain of types, which, however, can be united by the isomorphism from the fixed point theorem. We introduce the term zero, which arises from Maybe's Nothing and identify a successor function with repeated application of the Just. This way the natural numbers arise.
<span id="mwBKY"></span><span class="kr" id="mwBKc">type</span><span class="w" id="mwBKg"> </span><span class="kt" id="mwBKk">Nat</span><span class="w" id="mwBKo"> </span><span class="ow" id="mwBKs">=</span><span class="w" id="mwBKw"> </span><span class="kt" id="mwBK0">Fix</span><span class="w" id="mwBK4"> </span><span class="kt" id="mwBK8">Maybe</span> <span class="nf" id="mwBLA">zero</span><span class="w" id="mwBLE"> </span><span class="ow" id="mwBLI">::</span><span class="w" id="mwBLM"> </span><span class="kt" id="mwBLQ">Nat</span> <span class="nf" id="mwBLU">zero</span><span class="w" id="mwBLY"> </span><span class="ow" id="mwBLc">=</span><span class="w" id="mwBLg"> </span><span class="kt" id="mwBLk">Iso</span><span class="w" id="mwBLo"> </span><span class="kt" id="mwBLs">Nothing</span><span class="w" id="mwBLw"> </span><span class="c1" id="mwBL0">-- every 'Maybe a' has a term Nothing, and Iso maps it into a</span> <span class="nf" id="mwBL4">successor</span><span class="w" id="mwBL8"> </span><span class="ow" id="mwBMA">::</span><span class="w" id="mwBME"> </span><span class="kt" id="mwBMI">Nat</span><span class="w" id="mwBMM"> </span><span class="ow" id="mwBMQ">-></span><span class="w" id="mwBMU"> </span><span class="kt" id="mwBMY">Nat</span> <span class="nf" id="mwBMc">successor</span><span class="w" id="mwBMg"> </span><span class="ow" id="mwBMk">=</span><span class="w" id="mwBMo"> </span><span class="kt" id="mwBMs">Iso</span><span class="w" id="mwBMw"> </span><span class="o" id="mwBM0">.</span><span class="w" id="mwBM4"> </span><span class="kt" id="mwBM8">Just</span><span class="w" id="mwBNA"> </span><span class="c1" id="mwBNE">-- Just maps a to 'Maybe a' and Iso maps back to a new term</span>
<span id="mwBNQ"></span><span class="nf" id="mwBNU">pleaseWait</span><span class="w" id="mwBNY"> </span><span class="ow" id="mwBNc">::</span><span class="w" id="mwBNg"> </span><span class="kt" id="mwBNk">Algebra</span><span class="w" id="mwBNo"> </span><span class="kt" id="mwBNs">Maybe</span><span class="w" id="mwBNw"> </span><span class="kt" id="mwBN0">String</span><span class="w" id="mwBN4"> </span><span class="c1" id="mwBN8">-- again the silly f-algebra example from above</span> <span class="nf" id="mwBOA">pleaseWait</span><span class="w" id="mwBOE"> </span><span class="p" id="mwBOI">(</span><span class="kt" id="mwBOM">Just</span><span class="w" id="mwBOQ"> </span><span class="n" id="mwBOU">string</span><span class="p" id="mwBOY">)</span><span class="w" id="mwBOc"> </span><span class="ow" id="mwBOg">=</span><span class="w" id="mwBOk"> </span><span class="s" id="mwBOo">"wait.. "</span><span class="w" id="mwBOs"> </span><span class="o" id="mwBOw">++</span><span class="w" id="mwBO0"> </span><span class="n" id="mwBO4">string</span> <span class="nf" id="mwBO8">pleaseWait</span><span class="w" id="mwBPA"> </span><span class="kt" id="mwBPE">Nothing</span><span class="w" id="mwBPI"> </span><span class="ow" id="mwBPM">=</span><span class="w" id="mwBPQ"> </span><span class="s" id="mwBPU">"go!"</span>
Again, the following will evaluate to "wait.. wait.. wait.. wait.. go!": cata pleaseWait (successor.successor.successor.successor $ zero)
And now again the tree example. For this we must provide the tree container data type so that we can set up the fmap (we didn't have to do it for the Maybe functor, as it's part of the standard prelude).
<span id="mwBP0"></span><span class="kr" id="mwBP4">data</span><span class="w" id="mwBP8"> </span><span class="kt" id="mwBQA">Tcon</span><span class="w" id="mwBQE"> </span><span class="n" id="mwBQI">a</span><span class="w" id="mwBQM"> </span><span class="n" id="mwBQQ">b</span><span class="w" id="mwBQU"> </span><span class="ow" id="mwBQY">=</span><span class="w" id="mwBQc"> </span><span class="kt" id="mwBQg">TconL</span><span class="w" id="mwBQk"> </span><span class="n" id="mwBQo">a</span><span class="w" id="mwBQs"> </span><span class="o" id="mwBQw">|</span><span class="w" id="mwBQ0"> </span><span class="kt" id="mwBQ4">TconR</span><span class="w" id="mwBQ8"> </span><span class="n" id="mwBRA">b</span><span class="w" id="mwBRE"> </span><span class="n" id="mwBRI">b</span> <span class="kr" id="mwBRM">instance</span><span class="w" id="mwBRQ"> </span><span class="kt" id="mwBRU">Functor</span><span class="w" id="mwBRY"> </span><span class="p" id="mwBRc">(</span><span class="kt" id="mwBRg">Tcon</span><span class="w" id="mwBRk"> </span><span class="n" id="mwBRo">a</span><span class="p" id="mwBRs">)</span><span class="w" id="mwBRw"> </span><span class="kr" id="mwBR0">where</span> <span class="w" id="mwBR4"> </span><span class="n" id="mwBR8">fmap</span><span class="w" id="mwBSA"> </span><span class="n" id="mwBSE">f</span><span class="w" id="mwBSI"> </span><span class="p" id="mwBSM">(</span><span class="kt" id="mwBSQ">TconL</span><span class="w" id="mwBSU"> </span><span class="n" id="mwBSY">x</span><span class="p" id="mwBSc">)</span><span class="w" id="mwBSg"> </span><span class="ow" id="mwBSk">=</span><span class="w" id="mwBSo"> </span><span class="kt" id="mwBSs">TconL</span><span class="w" id="mwBSw"> </span><span class="n" id="mwBS0">x</span> <span class="w" id="mwBS4"> </span><span class="n" id="mwBS8">fmap</span><span class="w" id="mwBTA"> </span><span class="n" id="mwBTE">f</span><span class="w" id="mwBTI"> </span><span class="p" id="mwBTM">(</span><span class="kt" id="mwBTQ">TconR</span><span class="w" id="mwBTU"> </span><span class="n" id="mwBTY">y</span><span class="w" id="mwBTc"> </span><span class="n" id="mwBTg">z</span><span class="p" id="mwBTk">)</span><span class="w" id="mwBTo"> </span><span class="ow" id="mwBTs">=</span><span class="w" id="mwBTw"> </span><span class="kt" id="mwBT0">TconR</span><span class="w" id="mwBT4"> </span><span class="p" id="mwBT8">(</span><span class="n" id="mwBUA">f</span><span class="w" id="mwBUE"> </span><span class="n" id="mwBUI">y</span><span class="p" id="mwBUM">)</span><span class="w" id="mwBUQ"> </span><span class="p" id="mwBUU">(</span><span class="n" id="mwBUY">f</span><span class="w" id="mwBUc"> </span><span class="n" id="mwBUg">z</span><span class="p" id="mwBUk">)</span>
<span id="mwBUw"></span><span class="kr" id="mwBU0">type</span><span class="w" id="mwBU4"> </span><span class="kt" id="mwBU8">Tree</span><span class="w" id="mwBVA"> </span><span class="n" id="mwBVE">a</span><span class="w" id="mwBVI"> </span><span class="ow" id="mwBVM">=</span><span class="w" id="mwBVQ"> </span><span class="kt" id="mwBVU">Fix</span><span class="w" id="mwBVY"> </span><span class="p" id="mwBVc">(</span><span class="kt" id="mwBVg">Tcon</span><span class="w" id="mwBVk"> </span><span class="n" id="mwBVo">a</span><span class="p" id="mwBVs">)</span><span class="w" id="mwBVw"> </span><span class="c1" id="mwBV0">-- the initial algebra</span> <span class="nf" id="mwBV4">end</span><span class="w" id="mwBV8"> </span><span class="ow" id="mwBWA">::</span><span class="w" id="mwBWE"> </span><span class="n" id="mwBWI">a</span><span class="w" id="mwBWM"> </span><span class="ow" id="mwBWQ">-></span><span class="w" id="mwBWU"> </span><span class="kt" id="mwBWY">Tree</span><span class="w" id="mwBWc"> </span><span class="n" id="mwBWg">a</span> <span class="nf" id="mwBWk">end</span><span class="w" id="mwBWo"> </span><span class="ow" id="mwBWs">=</span><span class="w" id="mwBWw"> </span><span class="kt" id="mwBW0">Iso</span><span class="w" id="mwBW4"> </span><span class="o" id="mwBW8">.</span><span class="w" id="mwBXA"> </span><span class="kt" id="mwBXE">TconL</span> <span class="nf" id="mwBXI">meet</span><span class="w" id="mwBXM"> </span><span class="ow" id="mwBXQ">::</span><span class="w" id="mwBXU"> </span><span class="kt" id="mwBXY">Tree</span><span class="w" id="mwBXc"> </span><span class="n" id="mwBXg">a</span><span class="w" id="mwBXk"> </span><span class="ow" id="mwBXo">-></span><span class="w" id="mwBXs"> </span><span class="kt" id="mwBXw">Tree</span><span class="w" id="mwBX0"> </span><span class="n" id="mwBX4">a</span><span class="w" id="mwBX8"> </span><span class="ow" id="mwBYA">-></span><span class="w" id="mwBYE"> </span><span class="kt" id="mwBYI">Tree</span><span class="w" id="mwBYM"> </span><span class="n" id="mwBYQ">a</span> <span class="nf" id="mwBYU">meet</span><span class="w" id="mwBYY"> </span><span class="n" id="mwBYc">l</span><span class="w" id="mwBYg"> </span><span class="n" id="mwBYk">r</span><span class="w" id="mwBYo"> </span><span class="ow" id="mwBYs">=</span><span class="w" id="mwBYw"> </span><span class="kt" id="mwBY0">Iso</span><span class="w" id="mwBY4"> </span><span class="o" id="mwBY8">$</span><span class="w" id="mwBZA"> </span><span class="kt" id="mwBZE">TconR</span><span class="w" id="mwBZI"> </span><span class="n" id="mwBZM">l</span><span class="w" id="mwBZQ"> </span><span class="n" id="mwBZU">r</span>
<span id="mwBZg"></span><span class="nf" id="mwBZk">treeDepth</span><span class="w" id="mwBZo"> </span><span class="ow" id="mwBZs">::</span><span class="w" id="mwBZw"> </span><span class="kt" id="mwBZ0">Algebra</span><span class="w" id="mwBZ4"> </span><span class="p" id="mwBZ8">(</span><span class="kt" id="mwBaA">Tcon</span><span class="w" id="mwBaE"> </span><span class="n" id="mwBaI">a</span><span class="p" id="mwBaM">)</span><span class="w" id="mwBaQ"> </span><span class="kt" id="mwBaU">Integer</span><span class="w" id="mwBaY"> </span><span class="c1" id="mwBac">-- again, the treeDepth f-algebra example</span> <span class="nf" id="mwBag">treeDepth</span><span class="w" id="mwBak"> </span><span class="p" id="mwBao">(</span><span class="kt" id="mwBas">TconL</span><span class="w" id="mwBaw"> </span><span class="n" id="mwBa0">x</span><span class="p" id="mwBa4">)</span><span class="w" id="mwBa8"> </span><span class="ow" id="mwBbA">=</span><span class="w" id="mwBbE"> </span><span class="mi" id="mwBbI">1</span> <span class="nf" id="mwBbM">treeDepth</span><span class="w" id="mwBbQ"> </span><span class="p" id="mwBbU">(</span><span class="kt" id="mwBbY">TconR</span><span class="w" id="mwBbc"> </span><span class="n" id="mwBbg">y</span><span class="w" id="mwBbk"> </span><span class="n" id="mwBbo">z</span><span class="p" id="mwBbs">)</span><span class="w" id="mwBbw"> </span><span class="ow" id="mwBb0">=</span><span class="w" id="mwBb4"> </span><span class="mi" id="mwBb8">1</span><span class="w" id="mwBcA"> </span><span class="o" id="mwBcE">+</span><span class="w" id="mwBcI"> </span><span class="n" id="mwBcM">max</span><span class="w" id="mwBcQ"> </span><span class="n" id="mwBcU">y</span><span class="w" id="mwBcY"> </span><span class="n" id="mwBcc">z</span>
The following will evaluate to 4: cata treeDepth $ meet (end "X") (meet (meet (end "YXX") (end "YXY")) (end "YY"))

