# Theory of iteration and recursion

Recursion and iteration are two sides of the same coin. A common way to elaborate that idea is to express one in terms of the other. Iteration, recursively: to iterate an action, is to do the action, and then iterate the action again. Conversely, a recursive definition can be approximated by unfolding it iteratively. To implement recursion on a sequential machine, we can use a stack to keep track of those unfoldings.

So there is a sense in which these are equivalent, but that already presumes that they are not exactly the same. We think about recursion differently than iteration. Hence it may a little surprising when recursion and iteration both appear directly as two implementations of the same interface.

To summarize the main point without all the upcoming category theory jargon, there is one signature which describes an operator for iteration, recursion, or maybe a bit of both simultaneously, depending on how you read the symbols `==>`

and `+`

:

`iter :: (a ==> a + b) -> (a ==> b)`

## Iteration operator

The idea of “iteration” is encapsulated by the following function `iter`

:

```
iter :: (a -> Either a b) -> (a -> b)
iter f a =
case f a of
Left a' -> iter f a'
Right b -> b
```

`iter`

can be thought of as a “while” loop. The body of the loop `f`

takes some state `a`

, and either says “continue” with a new state `a'`

to keep the loop going, or “break” with a result `b`

.

## Iterative categories

We can generalize `iter`

. It transforms “loop bodies” into “loops”, and rather than functions, those could be entities in any category. An iteration operator on some category denoted `(==>)`

is a function with the following signature:

`iter :: (a ==> a + b) -> (a ==> b)`

satisfying a bunch of laws, with the most obvious one being a fixed point equation:^{1}

`iter f = (f >>> either (iter f) id)`

where `(>>>)`

and `id`

are the two defining components of a category, and `either`

is the eliminator for sums (`+`

). The technical term for “a category with sums” is a cocartesian category.

```
class Category k => Cocartesian k where
type a + b -- Not fully well-formed Haskell.
either :: k a c -> k b c -> k (a + b) c
left :: k a (a + b)
right :: k b (a + b)
-- Replacing k with an infix (==>)
-- either :: (a ==> c) -> (b ==> c) -> (a + b ==> c)
```

Putting this all together, an *iterative category* is a cocartesian category plus an `iter`

operation.

```
class Cocartesian k => Iterative k where
iter :: k a (a + b) -> k a b
```

The fixed point equation provides a pretty general way to define `iter`

. For the three in this post, it produces working functions in Haskell. In theory, properly sorting out issues of non-termination can get hairy.

```
iter :: (a -> Either a b) -> (a -> b)
iter f = f >>> either (iter f) id
-- NB: (>>>) = flip (.)
```

## Recursion operator

Recursion also provides an implementation for `iter`

, but in the opposite category, `(<==)`

. If you flip arrows back the right way, this defines a twin interface of “coiterative categories”. Doing so, sums `(+)`

become products `(*)`

.

```
class Cartesian k => Coiterative k where
coiter :: k (a * b) a -> k b a
-- with infix notation (==>) instead of k,
-- coiter :: (a * b ==> a) -> (b ==> a)
```

We can wrap any instance of `Iterative`

as an instance of `Coiterative`

and vice versa, so `iter`

and `coiter`

can be thought of as the same interface in principle. For particular implementations, one or the other direction may seem more intuitive.

If we curry and flip the argument, the type of `coiter`

becomes `(b -> a -> a) -> b -> a`

, which is like the type of `fix :: (a -> a) -> a`

but with the functor `(b -> _)`

applied to both the domain `(a -> a)`

and codomain `a`

: `coiter`

is `fmap fix`

.

```
coiter' :: (b -> a -> a) -> b -> a
coiter' = fmap fix
```

The fixed point equation provides an equivalent definition. We need to flip `(>>>)`

into `(<<<)`

(which is `(.)`

), and the dual of `either`

does not have a name in the standard library, but it is `liftA2 (,)`

.

```
coiter :: ((a, b) -> a) -> b -> a
coiter f = f . liftA2 (,) (coiter f) id
-- where --
liftA2 (,) :: (c -> a) -> (c -> b) -> (c -> (a, b))
```

That latter definition is mostly similar to the naive definition of `fix`

, where `fix f`

will be reevaluated with every unfolding.

```
fix :: (a -> a) -> a
fix f = f (fix f)
```

We have two implementations of `iter`

, one by iteration, one by recursion. Iterative categories thus provide a framework generalizing both iteration and recursion under the same algebraic rules.

From those two examples, one might hypothesize that `iter`

models iteration, while `coiter`

models recursion. But here is another example which suggests the situation is not as simple as that.

## Functor category, free monads

We start with the category of functors `Type -> Type`

, which is equipped with a sum:

`data (f :+: g) a = L (f a) | R (g a)`

But the real category of interest is the Kleisli category of the “monad of free monads”, *i.e.*, the mapping `Free`

from functors `f`

to the free monads they generate `Free f`

. That mapping is itself a monad.

`data Free f a = Pure a | Lift (f (Free f a))`

An arrow `f ==> g`

is now a natural transformation `f ~> Free g`

, *i.e.*, `forall a. f a -> Free g a`

:

```
-- Natural transformation from f to g
type f ~> g = forall a. f a -> g a
```

One intuition for that category is that functors `f`

are *interfaces*, and the free monad `Free f`

is inhabited by expressions, or *programs*, using operations from the interface `f`

. Then a natural transformation `f ~> Free g`

is an *implementation* of the interface `f`

using interface `g`

. Those operations compose naturally: given an implementation of `f`

in terms of `g`

(`f ~> Free g`

), and an implementation of `g`

in terms of `h`

(`g ~> Free h`

), we can obtain an implementation of `f`

in terms of `h`

(`f ~> Free h`

). Thus arrows `_ ~> Free _`

form a category—and that also mostly implies that `Free`

is a monad.

We can define `iter`

in that category. Like previous examples, we can define it without thinking by using the fixed point equation of `iter`

. We will call `rec`

this variant of `iter`

, because it actually behaves a lot like `fix`

whose name is already taken:

```
rec :: (f ~> Free (f :+: g)) -> (f ~> Free g)
rec f = f >>> either (rec f) id
-- where --
(>>>) :: (f ~> Free g) -> (g ~> Free h) -> (f ~> Free h)
id :: f ~> Free f
either :: (f ~> h) -> (g ~> h) -> (f :+: g ~> h)
```

We eventually do have to think about what `rec`

means.

The argument `f ~> Free (f :+: g)`

is a *recursive* implementation of an interface `f`

: it uses an interface `f :+: g`

which includes `f`

itself. `rec f`

composes `f`

with `either (rec f) id`

, which is basically some plumbing around `rec f`

. Consequently, `rec`

takes a recursive program `prog :: f ~> Free (f :+: g)`

, and produces a non-recursive program `f ~> Free g`

, using that same result to implement the `f`

calls in `prog`

, so only the other “external” calls in `g`

remain.

That third version of `iter`

(`rec`

) has similarities to both of the previous versions (`iter`

and `fix`

).

Obviously, the whole explanation above is given from perspective of recursion, or self-referentiality. While `fix`

simply describes recursion as fixed points, `rec`

provides a more elaborate model based on an explicit notion of syntax using `Free`

monads.

There is also a connection to the eponymous interpretation of `iter`

as iteration. Both `iter`

and `rec`

use a sum type (`Either`

or `(:+:)`

), representing a choice: to “continue” or “break” the loop, to “recurse” or “call” an external function.

## Control-flow graphs

That similarity may be more apparent when phrased in terms of low-level “assembly-like” languages, control-flow graphs. Here, programs consist of blocks of instructions, with “jump” instructions pointing to other blocks of instructions. Those programs form a category. The objects, *i.e.*, interfaces, are sets of “program labels” that one can jump to. A program `p : I ==> J`

exposes a set of “entry points” `I`

and a set of “exit points” `J`

: execution enters the program `p`

by jumping to a label in `I`

, and exits it by jumping to a label in `J`

. There may be other “internal jumps” within such a program, which are not visible in the interface `I ==> J`

.

The operation `iter : (I ==> I + J) -> (I ==> J)`

takes a program `p : I ==> I + J`

, whose exit points are in the disjoint union of `I`

and `J`

; `iter p : I ==> J`

is the result of linking the exit points in `I`

to the corresponding entry points, turning them into internal jumps. With some extra conditional constructs, we can easily implement “while” loops (“`iter`

on `_ -> _`

”) with such an operation.

Simple jumps (“jump to this label”) are pretty limited in expressiveness. We can make them more interesting by adding return locations to jumps, which thus become “calls” (“push a frame on the stack and jump to this label”)—to be complemented with “return” instructions. That generalization allows us to (roughly) implement `rec`

, suggesting that those various interpretations of `iter`

are maybe not as different as they seem.

```
iter :: (a ==> a + b) -> (a ==> b)
-- specializes to --
iter :: (a -> Either a b) -> (a -> b)
coiter :: ((a, b) -> a) -> (b -> a)
rec :: (f ~> Free (f :+: g)) -> (f ~> Free g)
```

The notion of “iterative category” is not quite standard; here is my version in Coq which condenses the little I could digest from the related literature (I mostly skip a lot and look for equations or commutative diagrams). Those and other relevant equations can be found in the book

*Iteration Theories: The Equational Logic of Iterative Processes*by Bloom and Ésik (in Section 5.2, Definition 5.2.1 (fixed point equation), and Theorems 5.3.1, 5.3.3, 5.3.9). It’s a pretty difficult book to just jump into though. The nice thing about category theory is that such dense formulas can be replaced with pretty pictures, like in this paper (page 7). For an additional source of diagrams and literature, a related notion is that of*traced monoidal categories*—every iterative category is traced monoidal.↩︎