# Recursion / Co-recursion

Matthias van der Hallen

The main idea is that co-recursion is the dual of recursion;

but in what sense?

Recursion

Co-recursion

• Terminology 'focuses' on the input (domain): an inductively defined datatype
• Inductively defined datatypes corresponds to a least fixpoint
• E.g. finite lists, finite trees, ... (data)
• Corresponds to a 'fold'
• Terminology 'focuses' on the output (codomain): a co-inductively defined datatype
• co-inductive datatype corresponds to a greatest fixpoint
• ​E.g. infinite lists (streams), infinite trees, ... (codata)
• Corresponds to an 'unfold'

### Example: Fibonacci

fibonacci :: Int -> Int
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci n = fibonacci (n-1) + fibonacci (n-2)

A recursive definition of fibonacci breaks down its argument and returns a number

The idea of this being a 'fold' is probably more relatable by looking at natural numbers as a Peano numbers

(e.g. $$S(S(S(S Zero)))$$)

### Example: Fibonacci

co-fibonacci :: Int -> Int -> [Int]
co-fibonacci a b = a cons co-fibonacci b (a+b)

A co-recursive definition of fibonacci builds an infinite list of fibonacci numbers by specifying part of the output

This function 'unfolds' a pair of integers into an (infinite) list of integers.

Note that in a language with support for codata, e.g. with lazy evaluation, infinite lists are not a problem.

(Literature suggests a link here with Prolog & tail recursion module cons - think of an accumulator - and possibly bottom-up / top-down through that)

### What if a function both breaks its arguments down and builds its result up?

Example: sorting functions with type
sort :: [a] -> [a]

• Can be seen as a fold, an unfold or a fold of an unfold (or vice versa)
• The paper 'A duality of sorts' views (pairs of) sorting algorithms as folds/unfolds of unfolds/folds.
• They make a nice comparison between insertion-sort and bubblesort

### The List type

NatListF f = Nil | Cons Nat f

Using open recursion instead of explicit recursion, and specializing to natural numbers, we can write

The least fixpoint is written as $$\mu \mathit{NatListF}$$, while the greatest fixpoint is written as $$\nu \mathit{NatListF}$$.

List a = Nil | Cons a List

We recognize this as the definition of a list:

NatListF f = Nil | Cons Nat f

The least fixpoint is written as $$\mu \mathit{NatListF}$$, while the greatest fixpoint is written as $$\nu \mathit{NatListF}$$.

Folding corresponds to using the isomorphism between $$\mu F$$ and $$F (\mu F)$$, as well as the algebra $$F a \rightarrow a$$

Unfolding corresponds to using the co-algebra $$a \rightarrow F a$$, as well as the isomorphism between $$F (\nu F)$$ and $$\nu F$$

### The List type

A slightly more complicated unfolding (futumorphism, *) can take into account the structure already unfolded.

(*): Every futumorphism can be rewritten into a (generalized) unfolding

Example: How to 'grow' a plant according to a complex set of rules based on one 'seed' value https://bit.ly/3ber6zv

Looking at the seed, it (randomly) branches, blooms or grows straight, leaving a new seed at the end of the structure

Note how at every 'iteration' (step), it looks as if we recurse through our result and expand where necessary; we co-recurse

### Does it correspond to the Owned Shares problem?

• By choosing a smart result datatype, we can probably provide a co-recursive view on the problem, but...
• it doesn't look like the process we want the solver to do, nor our semantical model

Nevertheless, I hope we all learned something

No (?)

### Although...

The paper "Mechanizing Coinduction and Corecursion in Higher-order Logic" states:

"With corecursion, the case analysis is driven by the output list, rather than the input list."

That definitely makes me think of function definitions like:

{
f(a,b) = pTrue <- p(a) & p(b).
f(a,b) = qTrue <- q(a) & q(b).
}

But I don't see it yet...

#### Recursion / co-Recursion

By Matthias van der Hallen

• 730