Lably
Skip to content

Corecursion

Type of algorithm in computer science

  • 17 min read
  • 5 chapters

Related on Lably

Through Computer science, Data structure and Natural number

Both corecursion and recursion can be thought of as operating on trees, which include data structures like lists and streams as special cases. Since recursion must terminate, it only works on trees that are well-founded, i.e. not infinitely deep, which are called data or initial data types; on the other hand, corecursion produces codata or final data types, which includes infinitely deep trees. Codata cannot be represented in memory directly, so is often implemented using self-referential data structures or lazy evaluation.

Data and codata

In total programming languages, the natural numbers may be defined as follows (using Haskell syntax):

<span id="mwJQ"></span><span class="kr" id="mwJg">data</span><span class="w" id="mwJw"> </span><span class="kt" id="mwKA">Nat</span><span class="w" id="mwKQ"> </span><span class="ow" id="mwKg">=</span><span class="w" id="mwKw"> </span><span class="kt" id="mwLA">Zero</span><span class="w" id="mwLQ"> </span><span class="o" id="mwLg">|</span><span class="w" id="mwLw"> </span><span class="kt" id="mwMA">Succ</span><span class="w" id="mwMQ"> </span><span class="kt" id="mwMg">Nat</span>

This states that every natural number is either zero or the successor of an existing natural number. For example, the number one is represented as Succ Zero, two as Succ (Succ Zero), three as Succ (Succ (Succ Zero)) and so on.

If we interpret the above declaration in an inductive way, then all natural numbers are generated like this, and we get our familiar set of natural numbers. Importantly, we can do recursion on this set: for example, we can use it to make a list that repeats a value n times:

<span id="mwQA"></span><span class="nf" id="mwQQ">repeat</span><span class="w" id="mwQg"> </span><span class="ow" id="mwQw">::</span><span class="w" id="mwRA"> </span><span class="n" id="mwRQ">a</span><span class="w" id="mwRg"> </span><span class="ow" id="mwRw">-></span><span class="w" id="mwSA"> </span><span class="kt" id="mwSQ">Nat</span><span class="w" id="mwSg"> </span><span class="ow" id="mwSw">-></span><span class="w" id="mwTA"> </span><span class="p" id="mwTQ">[</span><span class="n" id="mwTg">a</span><span class="p" id="mwTw">]</span> <span class="nf" id="mwUA">repeat</span><span class="w" id="mwUQ"> </span><span class="n" id="mwUg">x</span><span class="w" id="mwUw"> </span><span class="kt" id="mwVA">Zero</span><span class="w" id="mwVQ"> </span><span class="ow" id="mwVg">=</span><span class="w" id="mwVw"> </span><span class="kt" id="mwWA">[]</span><span class="w" id="mwWQ"> </span><span class="c1" id="mwWg">-- Base case</span> <span class="nf" id="mwWw">repeat</span><span class="w" id="mwXA"> </span><span class="n" id="mwXQ">x</span><span class="w" id="mwXg"> </span><span class="p" id="mwXw">(</span><span class="kt" id="mwYA">Succ</span><span class="w" id="mwYQ"> </span><span class="n" id="mwYg">n</span><span class="p" id="mwYw">)</span><span class="w" id="mwZA"> </span><span class="ow" id="mwZQ">=</span><span class="w" id="mwZg"> </span><span class="n" id="mwZw">x</span><span class="w" id="mwaA"> </span><span class="kt" id="mwaQ">:</span><span class="w" id="mwag"> </span><span class="n" id="mwaw">repeat</span><span class="w" id="mwbA"> </span><span class="n" id="mwbQ">x</span><span class="w" id="mwbg"> </span><span class="n" id="mwbw">n</span><span class="w" id="mwcA"> </span><span class="c1" id="mwcQ">-- Inductive step</span>

Note that the use of repeat x n is crucial—we could not have written repeat x (Succ n), because that is the function we are trying to define, and therefore it would loop forever. More specifically, the input must get smaller—or rather deeper, if seen as a data structure—each time we recurse.

The declaration may also be interpreted in a coinductive way, which may be denoted as:

<span id="mweQ"></span><span class="nf" id="mweg">codata</span><span class="w" id="mwew"> </span><span class="kt" id="mwfA">CoNat</span><span class="w" id="mwfQ"> </span><span class="ow" id="mwfg">=</span><span class="w" id="mwfw"> </span><span class="kt" id="mwgA">Zero</span><span class="w" id="mwgQ"> </span><span class="o" id="mwgg">|</span><span class="w" id="mwgw"> </span><span class="kt" id="mwhA">Succ</span><span class="w" id="mwhQ"> </span><span class="kt" id="mwhg">CoNat</span>

CoNat has all the natural numbers that Nat has automatically. But because codata can be infinitely deep, it has an extra term Succ (Succ (Succ (Succ …))) that continues on indefinitely—often denoted ∞. This is unique to the conatural numbers, so it can only be constructed using corecursion:

<span id="mwkQ"></span><span class="nf" id="mwkg">infinity</span><span class="w" id="mwkw"> </span><span class="ow" id="mwlA">::</span><span class="w" id="mwlQ"> </span><span class="kt" id="mwlg">CoNat</span> <span class="nf" id="mwlw">infinity</span><span class="w" id="mwmA"> </span><span class="ow" id="mwmQ">=</span><span class="w" id="mwmg"> </span><span class="kt" id="mwmw">Succ</span><span class="w" id="mwnA"> </span><span class="n" id="mwnQ">infinity</span>

While recursion requires that the input of the recursive call must get smaller each time, corecursion requires that the output of the recursive call must get larger each time. This is why we must write Succ infinity; just infinity = infinity would be disallowed as it loops forever.

To illustrate the duality between recursion and corecursion, we can encapsulate them in two functions, rec and corec. These functions' existence, together with the regular two constructors of Nat and CoNat, uniquely identify their respective types, and therefore allow rewriting all forms of recursion and corecursion in terms of them.

<span id="mwrA"></span><span class="nf" id="mwrQ">rec</span><span class="w" id="mwrg"> </span><span class="ow" id="mwrw">::</span><span class="w" id="mwsA"> </span><span class="kt" id="mwsQ">Nat</span><span class="w" id="mwsg"> </span><span class="ow" id="mwsw">-></span><span class="w" id="mwtA"> </span><span class="p" id="mwtQ">(</span><span class="kt" id="mwtg">Maybe</span><span class="w" id="mwtw"> </span><span class="n" id="mwuA">c</span><span class="w" id="mwuQ"> </span><span class="ow" id="mwug">-></span><span class="w" id="mwuw"> </span><span class="n" id="mwvA">c</span><span class="p" id="mwvQ">)</span><span class="w" id="mwvg"> </span><span class="ow" id="mwvw">-></span><span class="w" id="mwwA"> </span><span class="n" id="mwwQ">c</span> <span class="nf" id="mwwg">rec</span><span class="w" id="mwww"> </span><span class="kt" id="mwxA">Zero</span><span class="w" id="mwxQ"> </span><span class="n" id="mwxg">f</span><span class="w" id="mwxw"> </span><span class="ow" id="mwyA">=</span><span class="w" id="mwyQ"> </span><span class="n" id="mwyg">f</span><span class="w" id="mwyw"> </span><span class="kt" id="mwzA">Nothing</span> <span class="nf" id="mwzQ">rec</span><span class="w" id="mwzg"> </span><span class="p" id="mwzw">(</span><span class="kt" id="mw0A">Succ</span><span class="w" id="mw0Q"> </span><span class="n" id="mw0g">n</span><span class="p" id="mw0w">)</span><span class="w" id="mw1A"> </span><span class="n" id="mw1Q">f</span><span class="w" id="mw1g"> </span><span class="ow" id="mw1w">=</span><span class="w" id="mw2A"> </span><span class="n" id="mw2Q">f</span><span class="w" id="mw2g"> </span><span class="p" id="mw2w">(</span><span class="kt" id="mw3A">Just</span><span class="w" id="mw3Q"> </span><span class="p" id="mw3g">(</span><span class="n" id="mw3w">rec</span><span class="w" id="mw4A"> </span><span class="n" id="mw4Q">n</span><span class="w" id="mw4g"> </span><span class="n" id="mw4w">f</span><span class="p" id="mw5A">))</span> <span class="nf" id="mw5Q">corec</span><span class="w" id="mw5g"> </span><span class="ow" id="mw5w">::</span><span class="w" id="mw6A"> </span><span class="p" id="mw6Q">(</span><span class="n" id="mw6g">c</span><span class="w" id="mw6w"> </span><span class="ow" id="mw7A">-></span><span class="w" id="mw7Q"> </span><span class="kt" id="mw7g">Maybe</span><span class="w" id="mw7w"> </span><span class="n" id="mw8A">c</span><span class="p" id="mw8Q">)</span><span class="w" id="mw8g"> </span><span class="ow" id="mw8w">-></span><span class="w" id="mw9A"> </span><span class="n" id="mw9Q">c</span><span class="w" id="mw9g"> </span><span class="ow" id="mw9w">-></span><span class="w" id="mw-A"> </span><span class="kt" id="mw-Q">CoNat</span> <span class="nf" id="mw-g">corec</span><span class="w" id="mw-w"> </span><span class="n" id="mw_A">f</span><span class="w" id="mw_Q"> </span><span class="n" id="mw_g">base</span><span class="w" id="mw_w"> </span><span class="ow" id="mwAQA">=</span> <span class="w" id="mwAQE"> </span><span class="kr" id="mwAQI">case</span><span class="w" id="mwAQM"> </span><span class="n" id="mwAQQ">f</span><span class="w" id="mwAQU"> </span><span class="n" id="mwAQY">base</span><span class="w" id="mwAQc"> </span><span class="kr" id="mwAQg">of</span> <span class="w" id="mwAQk"> </span><span class="kt" id="mwAQo">Nothing</span><span class="w" id="mwAQs"> </span><span class="ow" id="mwAQw">-></span><span class="w" id="mwAQ0"> </span><span class="kt" id="mwAQ4">Zero</span> <span class="w" id="mwAQ8"> </span><span class="kt" id="mwARA">Just</span><span class="w" id="mwARE"> </span><span class="n" id="mwARI">x</span><span class="w" id="mwARM"> </span><span class="ow" id="mwARQ">-></span><span class="w" id="mwARU"> </span><span class="kt" id="mwARY">Succ</span><span class="w" id="mwARc"> </span><span class="p" id="mwARg">(</span><span class="n" id="mwARk">corec</span><span class="w" id="mwARo"> </span><span class="n" id="mwARs">f</span><span class="w" id="mwARw"> </span><span class="n" id="mwAR0">x</span><span class="p" id="mwAR4">)</span>

Conceptually, CoNat can be thought of as a state machine, where c is a type encapsulating the "current state". The function c -> Maybe c is a state transition function that either results in termination with Zero or continuation with Succ. We can rewrite the examples above using the functions:

<span id="mwASg"></span><span class="nf" id="mwASk">repeat</span><span class="w" id="mwASo"> </span><span class="n" id="mwASs">x</span><span class="w" id="mwASw"> </span><span class="n" id="mwAS0">n</span><span class="w" id="mwAS4"> </span><span class="ow" id="mwAS8">=</span><span class="w" id="mwATA"> </span><span class="n" id="mwATE">rec</span><span class="w" id="mwATI"> </span><span class="n" id="mwATM">n</span><span class="w" id="mwATQ"> </span><span class="p" id="mwATU">(</span><span class="nf" id="mwATY">\</span><span class="w" id="mwATc"> </span><span class="n" id="mwATg">s</span><span class="w" id="mwATk"> </span><span class="ow" id="mwATo">-></span> <span class="w" id="mwATs"> </span><span class="kr" id="mwATw">case</span><span class="w" id="mwAT0"> </span><span class="n" id="mwAT4">s</span><span class="w" id="mwAT8"> </span><span class="kr" id="mwAUA">of</span> <span class="w" id="mwAUE"> </span><span class="kt" id="mwAUI">Nothing</span><span class="w" id="mwAUM"> </span><span class="ow" id="mwAUQ">-></span><span class="w" id="mwAUU"> </span><span class="kt" id="mwAUY">[]</span> <span class="w" id="mwAUc"> </span><span class="kt" id="mwAUg">Just</span><span class="w" id="mwAUk"> </span><span class="n" id="mwAUo">a</span><span class="w" id="mwAUs"> </span><span class="ow" id="mwAUw">-></span><span class="w" id="mwAU0"> </span><span class="n" id="mwAU4">x</span><span class="w" id="mwAU8"> </span><span class="kt" id="mwAVA">:</span><span class="w" id="mwAVE"> </span><span class="n" id="mwAVI">a</span><span class="p" id="mwAVM">)</span> <span class="w" id="mwAVQ"> </span> <span class="nf" id="mwAVU">infinity</span><span class="w" id="mwAVY"> </span><span class="ow" id="mwAVc">=</span><span class="w" id="mwAVg"> </span><span class="n" id="mwAVk">corec</span><span class="w" id="mwAVo"> </span><span class="p" id="mwAVs">(</span><span class="nf" id="mwAVw">\</span><span class="w" id="mwAV0"> </span><span class="nb" id="mwAV4">()</span><span class="w" id="mwAV8"> </span><span class="ow" id="mwAWA">-></span><span class="w" id="mwAWE"> </span><span class="kt" id="mwAWI">Just</span><span class="w" id="mwAWM"> </span><span class="nb" id="mwAWQ">()</span><span class="p" id="mwAWU">)</span><span class="w" id="mwAWY"> </span><span class="nb" id="mwAWc">()</span>

A more complex example of codata is that of binary trees, where each node is either a leaf node, holding some data, or is a branch node that has exactly two children:

<span id="mwAWw"></span><span class="nf" id="mwAW0">codata</span><span class="w" id="mwAW4"> </span><span class="kt" id="mwAW8">BinaryTree</span><span class="w" id="mwAXA"> </span><span class="n" id="mwAXE">a</span><span class="w" id="mwAXI"> </span><span class="ow" id="mwAXM">=</span><span class="w" id="mwAXQ"> </span><span class="kt" id="mwAXU">Leaf</span><span class="w" id="mwAXY"> </span><span class="n" id="mwAXc">a</span><span class="w" id="mwAXg"> </span><span class="o" id="mwAXk">|</span><span class="w" id="mwAXo"> </span><span class="kt" id="mwAXs">Branch</span><span class="w" id="mwAXw"> </span><span class="p" id="mwAX0">(</span><span class="kt" id="mwAX4">BinaryTree</span><span class="w" id="mwAX8"> </span><span class="n" id="mwAYA">a</span><span class="p" id="mwAYE">)</span><span class="w" id="mwAYI"> </span><span class="p" id="mwAYM">(</span><span class="kt" id="mwAYQ">BinaryTree</span><span class="w" id="mwAYU"> </span><span class="n" id="mwAYY">a</span><span class="p" id="mwAYc">)</span>

This example has many more infinitely deep terms that can only be constructed by corecursion. For example, it can be infinitely deep only on the left-hand side, or on both sides, or alternating left and right:

<span id="mwAYs"></span><span class="nf" id="mwAYw">infiniteLeft</span><span class="w" id="mwAY0"> </span><span class="ow" id="mwAY4">::</span><span class="w" id="mwAY8"> </span><span class="n" id="mwAZA">a</span><span class="w" id="mwAZE"> </span><span class="ow" id="mwAZI">-></span><span class="w" id="mwAZM"> </span><span class="kt" id="mwAZQ">BinaryTree</span><span class="w" id="mwAZU"> </span><span class="n" id="mwAZY">a</span> <span class="nf" id="mwAZc">infiniteLeft</span><span class="w" id="mwAZg"> </span><span class="n" id="mwAZk">x</span><span class="w" id="mwAZo"> </span><span class="ow" id="mwAZs">=</span><span class="w" id="mwAZw"> </span><span class="kt" id="mwAZ0">Branch</span><span class="w" id="mwAZ4"> </span><span class="p" id="mwAZ8">(</span><span class="n" id="mwAaA">infiniteLeft</span><span class="w" id="mwAaE"> </span><span class="n" id="mwAaI">x</span><span class="p" id="mwAaM">)</span><span class="w" id="mwAaQ"> </span><span class="p" id="mwAaU">(</span><span class="kt" id="mwAaY">Leaf</span><span class="w" id="mwAac"> </span><span class="n" id="mwAag">x</span><span class="p" id="mwAak">)</span> <span class="nf" id="mwAao">infiniteBoth</span><span class="w" id="mwAas"> </span><span class="ow" id="mwAaw">::</span><span class="w" id="mwAa0"> </span><span class="kt" id="mwAa4">BinaryTree</span><span class="w" id="mwAa8"> </span><span class="n" id="mwAbA">a</span> <span class="nf" id="mwAbE">infiniteBoth</span><span class="w" id="mwAbI"> </span><span class="ow" id="mwAbM">=</span><span class="w" id="mwAbQ"> </span><span class="kt" id="mwAbU">Branch</span><span class="w" id="mwAbY"> </span><span class="n" id="mwAbc">infiniteBoth</span><span class="w" id="mwAbg"> </span><span class="n" id="mwAbk">infiniteBoth</span> <span class="nf" id="mwAbo">infiniteAlternating</span><span class="w" id="mwAbs"> </span><span class="ow" id="mwAbw">::</span><span class="w" id="mwAb0"> </span><span class="n" id="mwAb4">a</span><span class="w" id="mwAb8"> </span><span class="ow" id="mwAcA">-></span><span class="w" id="mwAcE"> </span><span class="kt" id="mwAcI">Bool</span><span class="w" id="mwAcM"> </span><span class="ow" id="mwAcQ">-></span><span class="w" id="mwAcU"> </span><span class="kt" id="mwAcY">BinaryTree</span><span class="w" id="mwAcc"> </span><span class="n" id="mwAcg">a</span> <span class="nf" id="mwAck">infiniteAlternating</span><span class="w" id="mwAco"> </span><span class="n" id="mwAcs">x</span><span class="w" id="mwAcw"> </span><span class="kt" id="mwAc0">False</span><span class="w" id="mwAc4"> </span><span class="ow" id="mwAc8">=</span><span class="w" id="mwAdA"> </span><span class="kt" id="mwAdE">Branch</span><span class="w" id="mwAdI"> </span><span class="p" id="mwAdM">(</span><span class="n" id="mwAdQ">infiniteAlternating</span><span class="w" id="mwAdU"> </span><span class="n" id="mwAdY">x</span><span class="w" id="mwAdc"> </span><span class="kt" id="mwAdg">True</span><span class="p" id="mwAdk">)</span><span class="w" id="mwAdo"> </span><span class="p" id="mwAds">(</span><span class="kt" id="mwAdw">Leaf</span><span class="w" id="mwAd0"> </span><span class="n" id="mwAd4">x</span><span class="p" id="mwAd8">)</span> <span class="nf" id="mwAeA">infiniteAlternating</span><span class="w" id="mwAeE"> </span><span class="n" id="mwAeI">x</span><span class="w" id="mwAeM"> </span><span class="kt" id="mwAeQ">True</span><span class="w" id="mwAeU"> </span><span class="ow" id="mwAeY">=</span><span class="w" id="mwAec"> </span><span class="kt" id="mwAeg">Branch</span><span class="w" id="mwAek"> </span><span class="p" id="mwAeo">(</span><span class="kt" id="mwAes">Leaf</span><span class="w" id="mwAew"> </span><span class="n" id="mwAe0">x</span><span class="p" id="mwAe4">)</span><span class="w" id="mwAe8"> </span><span class="p" id="mwAfA">(</span><span class="n" id="mwAfE">infiniteAlternating</span><span class="w" id="mwAfI"> </span><span class="n" id="mwAfM">x</span><span class="w" id="mwAfQ"> </span><span class="kt" id="mwAfU">False</span><span class="p" id="mwAfY">)</span>

Again, corecursion on binary trees has a more general form based on a "state machine"-like constructor:

<span id="mwAfo"></span><span class="nf" id="mwAfs">corec</span><span class="w" id="mwAfw"> </span><span class="ow" id="mwAf0">::</span><span class="w" id="mwAf4"> </span><span class="p" id="mwAf8">(</span><span class="n" id="mwAgA">c</span><span class="w" id="mwAgE"> </span><span class="ow" id="mwAgI">-></span><span class="w" id="mwAgM"> </span><span class="kt" id="mwAgQ">Either</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="n" id="mwAgk">c</span><span class="p" id="mwAgo">,</span><span class="w" id="mwAgs"> </span><span class="n" id="mwAgw">c</span><span class="p" id="mwAg0">))</span><span class="w" id="mwAg4"> </span><span class="ow" id="mwAg8">-></span><span class="w" id="mwAhA"> </span><span class="n" id="mwAhE">c</span><span class="w" id="mwAhI"> </span><span class="ow" id="mwAhM">-></span><span class="w" id="mwAhQ"> </span><span class="kt" id="mwAhU">BinaryTree</span><span class="w" id="mwAhY"> </span><span class="n" id="mwAhc">a</span> <span class="nf" id="mwAhg">corec</span><span class="w" id="mwAhk"> </span><span class="n" id="mwAho">f</span><span class="w" id="mwAhs"> </span><span class="n" id="mwAhw">base</span><span class="w" id="mwAh0"> </span><span class="ow" id="mwAh4">=</span> <span class="w" id="mwAh8"> </span><span class="kr" id="mwAiA">case</span><span class="w" id="mwAiE"> </span><span class="n" id="mwAiI">f</span><span class="w" id="mwAiM"> </span><span class="n" id="mwAiQ">base</span><span class="w" id="mwAiU"> </span><span class="kr" id="mwAiY">of</span> <span class="w" id="mwAic"> </span><span class="kt" id="mwAig">Left</span><span class="w" id="mwAik"> </span><span class="n" id="mwAio">x</span><span class="w" id="mwAis"> </span><span class="ow" id="mwAiw">-></span><span class="w" id="mwAi0"> </span><span class="kt" id="mwAi4">Leaf</span><span class="w" id="mwAi8"> </span><span class="n" id="mwAjA">x</span> <span class="w" id="mwAjE"> </span><span class="kt" id="mwAjI">Right</span><span class="w" id="mwAjM"> </span><span class="p" id="mwAjQ">(</span><span class="n" id="mwAjU">x</span><span class="p" id="mwAjY">,</span><span class="w" id="mwAjc"> </span><span class="n" id="mwAjg">y</span><span class="p" id="mwAjk">)</span><span class="w" id="mwAjo"> </span><span class="ow" id="mwAjs">-></span><span class="w" id="mwAjw"> </span><span class="kt" id="mwAj0">Branch</span><span class="w" id="mwAj4"> </span><span class="p" id="mwAj8">(</span><span class="n" id="mwAkA">corec</span><span class="w" id="mwAkE"> </span><span class="n" id="mwAkI">f</span><span class="w" id="mwAkM"> </span><span class="n" id="mwAkQ">x</span><span class="p" id="mwAkU">)</span><span class="w" id="mwAkY"> </span><span class="p" id="mwAkc">(</span><span class="n" id="mwAkg">corec</span><span class="w" id="mwAkk"> </span><span class="n" id="mwAko">f</span><span class="w" id="mwAks"> </span><span class="n" id="mwAkw">y</span><span class="p" id="mwAk0">)</span>

M-types

In a dependently-typed setting, codata can be encoded using M-types, which are dual to W-types. Given a type A and an A-indexed family of types B, one can form the M-type Ma:AB(a), representing the type of trees whose nodes are labelled with elements of A and who child nodes are indexed by the set B(a). In pseudocode, M-types (and their corecursion principle) may be defined as:

<span id="mwAl0"></span><span class="nf" id="mwAl4">codata</span><span class="w" id="mwAl8"> </span><span class="kt" id="mwAmA">M</span><span class="w" id="mwAmE"> </span><span class="n" id="mwAmI">a</span><span class="w" id="mwAmM"> </span><span class="p" id="mwAmQ">(</span><span class="n" id="mwAmU">b</span><span class="w" id="mwAmY"> </span><span class="ow" id="mwAmc">::</span><span class="w" id="mwAmg"> </span><span class="n" id="mwAmk">a</span><span class="w" id="mwAmo"> </span><span class="ow" id="mwAms">-></span><span class="w" id="mwAmw"> </span><span class="o" id="mwAm0">*</span><span class="p" id="mwAm4">)</span><span class="w" id="mwAm8"> </span><span class="ow" id="mwAnA">=</span><span class="w" id="mwAnE"> </span><span class="kt" id="mwAnI">M</span> <span class="w" id="mwAnM"> </span><span class="p" id="mwAnQ">{</span><span class="w" id="mwAnU"> </span><span class="n" id="mwAnY">root</span><span class="w" id="mwAnc"> </span><span class="ow" id="mwAng">::</span><span class="w" id="mwAnk"> </span><span class="n" id="mwAno">a</span> <span class="w" id="mwAns"> </span><span class="p" id="mwAnw">,</span><span class="w" id="mwAn0"> </span><span class="n" id="mwAn4">branch</span><span class="w" id="mwAn8"> </span><span class="ow" id="mwAoA">::</span><span class="w" id="mwAoE"> </span><span class="n" id="mwAoI">b</span><span class="w" id="mwAoM"> </span><span class="n" id="mwAoQ">root</span><span class="w" id="mwAoU"> </span><span class="ow" id="mwAoY">-></span><span class="w" id="mwAoc"> </span><span class="kt" id="mwAog">M</span><span class="w" id="mwAok"> </span><span class="n" id="mwAoo">a</span><span class="w" id="mwAos"> </span><span class="n" id="mwAow">b</span><span class="w" id="mwAo0"> </span><span class="p" id="mwAo4">}</span><span class="w" id="mwAo8"> </span> <span class="w" id="mwApA"> </span> <span class="nf" id="mwApE">corec</span><span class="w" id="mwApI"> </span><span class="ow" id="mwApM">::</span><span class="w" id="mwApQ"> </span><span class="p" id="mwApU">(</span><span class="n" id="mwApY">c</span><span class="w" id="mwApc"> </span><span class="ow" id="mwApg">-></span><span class="w" id="mwApk"> </span><span class="p" id="mwApo">(</span><span class="n" id="mwAps">root</span><span class="w" id="mwApw"> </span><span class="ow" id="mwAp0">::</span><span class="w" id="mwAp4"> </span><span class="n" id="mwAp8">a</span><span class="p" id="mwAqA">,</span><span class="w" id="mwAqE"> </span><span class="n" id="mwAqI">b</span><span class="w" id="mwAqM"> </span><span class="n" id="mwAqQ">root</span><span class="w" id="mwAqU"> </span><span class="ow" id="mwAqY">-></span><span class="w" id="mwAqc"> </span><span class="n" id="mwAqg">c</span><span class="p" id="mwAqk">))</span><span class="w" id="mwAqo"> </span><span class="ow" id="mwAqs">-></span><span class="w" id="mwAqw"> </span><span class="n" id="mwAq0">c</span><span class="w" id="mwAq4"> </span><span class="ow" id="mwAq8">-></span><span class="w" id="mwArA"> </span><span class="kt" id="mwArE">M</span><span class="w" id="mwArI"> </span><span class="n" id="mwArM">a</span><span class="w" id="mwArQ"> </span><span class="n" id="mwArU">b</span> <span class="nf" id="mwArY">corec</span><span class="w" id="mwArc"> </span><span class="n" id="mwArg">f</span><span class="w" id="mwArk"> </span><span class="n" id="mwAro">base</span><span class="w" id="mwArs"> </span><span class="ow" id="mwArw">=</span> <span class="w" id="mwAr0"> </span><span class="kr" id="mwAr4">let</span><span class="w" id="mwAr8"> </span><span class="p" id="mwAsA">(</span><span class="n" id="mwAsE">root</span><span class="p" id="mwAsI">,</span><span class="w" id="mwAsM"> </span><span class="n" id="mwAsQ">branch</span><span class="p" id="mwAsU">)</span><span class="w" id="mwAsY"> </span><span class="ow" id="mwAsc">=</span><span class="w" id="mwAsg"> </span><span class="n" id="mwAsk">f</span><span class="w" id="mwAso"> </span><span class="n" id="mwAss">base</span> <span class="w" id="mwAsw"> </span><span class="kr" id="mwAs0">in</span><span class="w" id="mwAs4"> </span><span class="kt" id="mwAs8">M</span><span class="w" id="mwAtA"> </span><span class="p" id="mwAtE">{</span><span class="w" id="mwAtI"> </span><span class="n" id="mwAtM">root</span><span class="w" id="mwAtQ"> </span><span class="ow" id="mwAtU">=</span><span class="w" id="mwAtY"> </span><span class="n" id="mwAtc">root</span><span class="p" id="mwAtg">,</span><span class="w" id="mwAtk"> </span><span class="n" id="mwAto">branch</span><span class="w" id="mwAts"> </span><span class="ow" id="mwAtw">=</span><span class="w" id="mwAt0"> </span><span class="nf" id="mwAt4">\</span><span class="w" id="mwAt8"> </span><span class="n" id="mwAuA">i</span><span class="w" id="mwAuE"> </span><span class="ow" id="mwAuI">-></span><span class="w" id="mwAuM"> </span><span class="n" id="mwAuQ">corec</span><span class="w" id="mwAuU"> </span><span class="n" id="mwAuY">f</span><span class="w" id="mwAuc"> </span><span class="p" id="mwAug">(</span><span class="n" id="mwAuk">branch</span><span class="w" id="mwAuo"> </span><span class="n" id="mwAus">i</span><span class="p" id="mwAuw">)</span><span class="w" id="mwAu0"> </span><span class="p" id="mwAu4">}</span>

As an example, the natural and conatural numbers may be constructed as W- and M-types of the same function:

<span id="mwAvI"></span><span class="nf" id="mwAvM">f</span><span class="w" id="mwAvQ"> </span><span class="ow" id="mwAvU">::</span><span class="w" id="mwAvY"> </span><span class="kt" id="mwAvc">Bool</span><span class="w" id="mwAvg"> </span><span class="ow" id="mwAvk">-></span><span class="w" id="mwAvo"> </span><span class="o" id="mwAvs">*</span> <span class="nf" id="mwAvw">f</span><span class="w" id="mwAv0"> </span><span class="kt" id="mwAv4">False</span><span class="w" id="mwAv8"> </span><span class="ow" id="mwAwA">=</span><span class="w" id="mwAwE"> </span><span class="kt" id="mwAwI">Void</span><span class="w" id="mwAwM"> </span><span class="c1" id="mwAwQ">-- Zero case (no branches)</span> <span class="nf" id="mwAwU">f</span><span class="w" id="mwAwY"> </span><span class="kt" id="mwAwc">True</span><span class="w" id="mwAwg"> </span><span class="ow" id="mwAwk">=</span><span class="w" id="mwAwo"> </span><span class="nb" id="mwAws">()</span><span class="w" id="mwAww"> </span><span class="c1" id="mwAw0">-- Succ case (one branch)</span> <span class="kt" id="mwAw4">Nat</span><span class="w" id="mwAw8"> </span><span class="ow" id="mwAxA">=</span><span class="w" id="mwAxE"> </span><span class="kt" id="mwAxI">W</span><span class="w" id="mwAxM"> </span><span class="kt" id="mwAxQ">Bool</span><span class="w" id="mwAxU"> </span><span class="n" id="mwAxY">f</span> <span class="kt" id="mwAxc">CoNat</span><span class="w" id="mwAxg"> </span><span class="ow" id="mwAxk">=</span><span class="w" id="mwAxo"> </span><span class="kt" id="mwAxs">M</span><span class="w" id="mwAxw"> </span><span class="kt" id="mwAx0">Bool</span><span class="w" id="mwAx4"> </span><span class="n" id="mwAx8">f</span>

M-types can be proven to exist in many elementary topoi, and their existence follows from the existence of W-types.

Sign in to keep reading

4 more chapters are free with a Lably account.

More in Computing and communication