2.4 Generalizations
Iteration can be understood as a technique for the in-
ductive definition of a function with initial algebra do-
main, (|α|)
T
: µT → A, by giving a T -algebra (A, α)
that defines one recursive step of the function. In the
signature functor T , base and induction cases are dealt
with together. The technique can easily be seen to
subsume, for the Peano functor N, classical complete
induction. The defining form α(a) is allowed to use
only the recursive function results for immediate sub-
arguments, a − 1 in the case of N.
Not all functions are conveniently presented in
this form, though: for instance, the factorial function
fac(n) requires both the recursive result fac(n − 1)
and the original argument n, and the Fibonacci func-
tion fib(n) requires two recursive results, fib(n − 1)
and fib(n − 2). Consequently, more complicated pat-
terns of recursion than the one catered for by iteration
are also studied. Recursive functions that work like
fac are handled with the primitive recursion pattern
which, for the Peano functor, is the classical form of
total recursion theory. Recursive functions that work
like fib, or more generally, require recursive function
results for arbitrary simpler arguments, are handled
with the course-of-value iteration pattern, which we
shall focus on for the following investigations.
Note that, in a setting with arbitrary datatypes de-
finable as functors, all total recursion schemes are es-
sentially equivalent in the sense that they can simu-
late each other in extended datatypes. Note also that
higher-order functions, operating on datatypes con-
taining computable functions, are strictly more pow-
erful than the first-order functions, which are dealt
with comprehensively in the classical theory via nat-
ural numbers and G
¨
odel encoding. For instance, the
archetypical example of a computable function that
is not primitively recursive in the classical sense, the
Ackermann function ack, turns out to be not just prim-
itively recursive, but even iterative, in a higher-order
setting: Consider the higher-order N-algebra ([N →
N],α) over the space of iterative functions on N,
where α()(n) = n+ 1 and α( f
0
) = (|β
f
|), referring to
the f -indexed family of nested first-order N-algebras
(N,β
f
) where β
f
() = f (1) and β
f
(n
0
) = f (n). To
verify that ack(m,n) = (|α|)(m)(n) holds is left as an
exercise to the reader.
2.5 Course-of-Value Iteration
The categorial form of course-of-value (cov) iteration
(Uustalu and Vene, 1999) manages recursive function
results by considering, besides the functor T whose
initial algebra is the intended function domain, an ex-
tended functor T
C
, defined as T
C
(X) = C ×T (X ) and
T
C
( f ) = id
C
×T ( f ), where C is the intended function
range. It can be understood as specifying the same al-
gebraic signature as T , but with an additional annota-
tion of a value from C. The intuition is that T speci-
fies one level of structure of a function argument, and
T
C
pairs that with the function result. Then νT
C
is
the space of arbitrarily (even infinitely) deeply nested
function arguments with results annotated at all levels
of nesting, and T (νT
C
) is the same, except that the
result for the top level is missing. The whole point
of cov iteration is to fill that hole. The cov induction
principle can hence be put as follows:
For any set C and generator ϕ : T (νT
C
) → C,
there is a unique recursive function {|ϕ|}
T
:
µT → C.
7
This terse statement is much illuminated by an ex-
ample. For the Peano functor N, the extension N
C
looks very similar to the list functor L
C
, except that
the structure elements (C×) and (1+) are exchanged.
Consequently, the final N
C
-coalgebra is almost the
same, except that the empty list is excluded, mak-
ing deconstruction total: νN
C
= C
+∞
= C
+
∪C
ω
and
out
N
C
(c · ) = (c, ). The set N(νN
C
) can then be un-
derstood as re-including the empty list, denoted by
: N(νN
C
)
∼
=
C
∞
. We take the liberty to implicitly
conflate the two sets. Now let C = N and consider
the generator defined as ϕ(ε) = 0, ϕ(a · ε) = 1 and
ϕ(a · b · ε) = a + b. This defines the Fibonacci func-
tion: fib = {|ϕ|}
N
.
Compared with ordinary iteration, cov functions
often have multiple base cases, because their depen-
dence on results for subarguments may exceed the
nesting depth of the argument given. For the Fi-
bonacci function, each value depends on the two pre-
ceding ones, so base cases for arguments less than two
are required. The presentation can often be simpli-
fied, and all base cases handled with a single math-
ematical object, by specifying a default, infinite sur-
rogate history that is appended to any finite input to
the cov generator. Formally, the generator ϕ : C
∞
→ C
can be decomposed into an infinite list h ∈ C
ω
and a
generator without base cases
ϕ : C
ω
→ C, such that
ϕ = ϕ ◦ append(h). For some cov iterations, espe-
cially time-invertible ones, there is a natural candi-
date for h that eliminates the base cases completely.
For the Fibonacci function, set ϕ(a · b · ) = a + b and
h = (+1) · (−1)···; surrogate elements after the sec-
ond are never used and hence arbitrary. Where no
such natural surrogate history can be found, add a dis-
tinguished “end” element to C and handle base cases
7
The exact relation of {|·|} to unique (co)algebra homo-
morphisms is technically involved and out of scope here.
ENASE2012-7thInternationalConferenceonEvaluationofNovelSoftwareApproachestoSoftwareEngineering
150