Conference PaperPDF Available

Computation by Prophecy

Authors:

Abstract

We describe a new method to represent (partial) recursive functions in type theory. For every recursive definition, we define a co-inductive type of prophecies that characterises the traces of the computation of the function. The structure of a prophecy is a possibly infinite tree, which is coerced by linearisation to a type of partial results defined by applying the delay monad to the co-domain of the function. Using induction on a weight relation defined on the prophecies, we can reason about them and prove that the formal type-theoretic version of the recursive function, resulting from the present method, satisfies the recursive equations of the original function. The advantages of this technique over the method previously developed by the authors via a special-purpose accessibility (domain) predicate are: there is no need of extra logical arguments in the definition of the recursive function; the function can be applied to any element in its domain, regardless of termination properties; we obtain a type of partial recursive functions between any two given types; and composition of recursive functions can be easily defined.
Computation by Prophecy
Ana Bove1and Venanzio Capretta2
1Department of Computer Science and Engineering
Chalmers University of Technology,
412 96 oteborg, Sweden
Tel.: +46-31-7721020, Fax: +46-31-7723663
bove@chalmers.se
2Computer Science Institute (iCIS),
Radboud University Nijmegen,
Tel.: +31-24-3652631, Fax: +31-24-3652525
venanzio@cs.ru.nl
Abstract. We describe a new method to represent (partial) recursive
functions in type theory. For every recursive definition, we define a
co-inductive type of prophecies that characterises the traces of the com-
putation of the function. The structure of a prophecy is a possibly infinite
tree, which is coerced by linearisation to a type of partial results defined
by applying the delay monad to the co-domain of the function. Using
induction on a weight relation defined on the prophecies, we can reason
about them and prove that the formal type-theoretic version of the recur-
sive function, resulting from the present method, satisfies the recursive
equations of the original function. The advantages of this technique over
the method previously developed by the authors via a special-purpose
accessibility (domain) predicate are: there is no need of extra logical ar-
guments in the definition of the recursive function; the function can be
applied to any element in its domain, regardless of termination prop-
erties; we obtain a type of partial recursive functions between any two
given types; and composition of recursive functions can be easily defined.
1 Introduction
The implementation of general recursive functions in type theory has received
wide attention in the last decade, and several methods to implement recursive
algorithms and reason about them have been described in the literature.
We give a survey of different approaches in the related work section of a
previous article [6]. After the publication of that paper, the type-theory based
proof assistant Coq [14,3] has been extended with a new feature to define total
recursive functions that expands the native structural recursion. The feature
Function (based on the work by Balaa and Bertot [1]) facilitates the definition of
total functions that have a well-founded relation associated to them. In addition,
the tactic functional induction (based on the work by Barthe and Courtieu
[2]) has been added to the system, providing induction principles that follow
the definition of structurally recursive functions. These contributions enlarge
S. Ronchi Della Rocca (Ed.): TLCA 2007, LNCS 4583, pp. 70–83, 2007.
c
Springer-Verlag Berlin Heidelberg 2007
Computation by Prophecy 71
the class of total recursive functions that can be studied in Coq.Thereare,
however, functions that lay outside the reach of these new features, for example,
all strictly partial recursive functions. Our main goal in this work is to provide
a good general type-theoretic treatment of recursive computations (partial or
not).
We have previously worked on two methods to tackle this issue. The first
method [6,4,7] consists in characterising the inputs on which the function ter-
minates by an inductive (domain) predicate easily defined from the recursive
equations, and then defining the function itself by recursion on the proof that
the input argument satisfies this domain predicate. The second method [8] con-
sists in defining co-inductive types of partial elements and implementing general
recursive functions by co-recursion on these types.
Both methods have pros and cons.
The first method has two main advantages. First, the type-theoretic equa-
tions defining the function are almost identical to the recursive equations in a
functional programming language, except that the former require proof terms
for the domain predicate as additional arguments. Second, it is easy to reason
about a function formalised with this method by induction on its domain pred-
icate. A disadvantage is that the application of a function to a certain input
always requires a proof that the input satisfies the domain predicate defined for
the function; as a consequence, the function can only be applied to arguments
for which we know how to construct such a proof.
On the other hand, a function formalised with the second method requires
no additional logical arguments in its definition and, hence, the function can be
applied even to arguments for which it might not terminate. The main disad-
vantage is that reasoning about functions formalised in this way is much more
involved than with the first method.
Here, we show a new way of representing general recursive functions in in-
tensional type theory, where we adapt some of the ideas of the first method
to facilitate the definition of functions with the second one and the subsequent
reasoning about their formalisation. In other words, we propose a co-inductive
version of the Bove/Capretta method.
Throughout this paper we will use a generalisation of the Fibonacci function
as a running example to illustrate the notions we are presenting. This algorithm
is defined as follows:
F:NN
F0=a
F1=b+cF(g0)
F(S(Sn)) = F(gn)+F(g(Sn)).
where a,band care natural numbers and g:NN. We can get the standard
Fibonacci sequence by letting a=1,b=1,c= 0, and letting gbe the identity
function.
Observe that the totality of Fdepends on the definition of g:withthesame
choices of a,b,c, but choosing for gthe successor function, we obtain a function
that is defined in 0 but diverges for any other value.
72 A. Bove and V. Capretta
This paper is organised as follows. In Section 2, we recall how to define a
recursive function with the inductive Bove/Capretta method. Sections 3 and
4 present, respectively, the prophecies, that is, the co-inductive version of the
Bove/Capretta method, and their evaluation procedure. In Section 5, we show
the validity of this new method. Finally, Section 6 presents some conclusions.
We have formalised the running example in the proof assistant Coq.Asan
additional example, we have also formalised the quicksort algorithm using the
method we present here. The files of both formalisations are available on the
web at the address: http://www.cs.ru.nl/~venanzio/Coq/prophecy.html.
2 Overview of the Bove/Capretta Method
We outline the general steps of the inductive Bove/Capretta method by showing
how an algorithm defined by general recursive equations can be formalised in
type theory.
Let fbe a recursive function defined by a series of (non-overlapping) equa-
tions. We assume that the informal definition of the function has the following
form: f:AB
···
fp=e[(fp
1),...,(fp
n)]
···
where fp=··· is one of the recursive equations defining f.Thetermpis
a pattern, possibly containing variables that can occur in the right-hand side of
the equation. The right-hand side is an expression e, recursively calling fon the
arguments p1,...,p
n.
For an ar gument amatching the pattern p, there are three phases in the com-
putation of (fa): first, from the argument a, the recursive arguments a1,...,a
n
are computed; then, the program fis recursively applied to these arguments;
and finally, the results of the recursive calls are fed into the operator eto obtain
the final result. This three-steps process is general and can be used to give a
very abstract notion of computable function [9].
We recall that the Bove/Capretta method consists in characterising the do-
main of a function by an inductive predicate with (in principle) one constructor
for each of the equations defining the function1. The constructor corresponding
to each equation takes as parameters assumptions stating that the recursive ar-
guments in the equation satisfy the domain predicate. The general form of the
domain predicate for the function faboveisasfollows:
Df:AProp
···
dp:(Γp)(Dfp1)···(Dfpn)(Dfp)
···
1Equations with a case-expression on their right-hand side can give raise to sev-
eral constructors. See [6] for a more detailed explanation on how to handle these
equations.
Computation by Prophecy 73
where Γpis a context local to the equation, comprising the variables that occur
in p.
For our example we have
DF:NProp
d0:(DF0)
d1:(DF(g0)) (DF1)
dS:(n:N)(DF(gn)) (DF(g(Sn))) (DF(S(Sn)))
The type-theoretic version of ftakes as an extra argument a proof that the
input satisfies the domain predicate, and it is defined by structural recursion on
this extra argument:
f:(y:A)(Dfy)B
···
fp(dp
xh
1··· hn)=e[(fp
1h1),...,(fp
nhn)]
···
For the Ffunction we get:
F:(m:N)(DFm)N
F0d0=a
F1(d1h)=b+c(F(g0) h)
F(S(Sn)) (dSnh
1h2)=F(gn)h1+F(g(Sn)) h2
For a complete description of this method and for more examples of its appli-
cation, the reader is referred to [6,4,7].
3 Views and Prophecies
We can consider an alternative representation of the domain Dfof fwhere we
ignore the elements of Aaltogether. Below we present the general form of this
new domain type which we call Af, and its corresponding instance for the F
function which we call NF.
Af:Typ e
···
cp:ΓpAf···Af

ntimes
Af
···
NF:Typ e
c0:NF
c1:NFNF
cS:NNFNFNF
Using the terminology of [12], we call Afaview of the domain.
We now formalise fas a function on this new type:
f:AfB
···
f(cp
xt
1··· tn)=e[(ft1),...,(ftn)]
···
74 A. Bove and V. Capretta
The variables in Γpare still required as parameters of the constructor cp,even
if they do not occur in the arguments of the branches, since they may occur in
the operator e.
For our example we obtain
F:NFN
Fc0=a
F(c1h)=b+c(Fh)
F(cSnh
1h2)=Fh1+Fh2
We can see Afas the type of abstract inputs for the function f.Itiseasyto
obtain the elements in Affrom the elements of Asatisfying Df:
ıf:(y:A)(Dfy)Af
···
ıfp(dp
xh
1···hn)=cp
x(ıfp1h1)···(ıfpnhn)
···
The reverse direction is however not possible, since elements in Afcan be con-
structed in an arbitrary way, completely disconnected from the behaviour of the
function f. The possible projections of those elements in Ahave absolutely no
reason to satisfy Df. Consider for example the element (cS10 c0c0) for our
example of the function F.
We now try to dualise the inductive Bove/Capretta method by using a
co-inductive approach. The idea is that, instead of defining an inductive char-
acterisation of the domain, we define a co-inductive characterisation of the
co-domain of the function:
CoInductive Bf:Typ e
···
be:ΓeBf···Bf

ntimes Bf
···
where Γeis the context comprising the variables occurring free in e. In principle,
Γecould coincide with Γp; however, some of the variables in the pattern pmay
not be needed for the computation of eand hence, they could be omitted in Γe2.
Observe that the definition of Bfis identical to that of Afexcept for the
contexts appearing in the equations of both definitions, and for the fact that it
is a co-inductive definition instead of an inductive one.
The co-inductive characterisation of the co-domain of Fis defined as
CoInductive NF:Typ e
f0:NF
f1:NFNF
fS:NFNFNF.
2Actually, in some cases, not even all the variables that are free in eneed to be
included in Γe; for example, the Natural argument nis omitted from the constructor
fSin the definition of NF.
Computation by Prophecy 75
We now give a version of fthat has Bfas co-domain:
f:ABf
···
fp=be
x(fp1)···(fpn)
···
This definition is sound because the co-recursive calls (fp1),...,(fpn)are
guarded by the constructor be(see [11] for further reading on this issue).
We can see Bfasthetypeofabstract outputs in the same way we saw Afas
the type of abstract inputs. In a certain sense, the elements of Bfare a prediction
of the structure of the result. For this reason we will call them prophecies.
The version of Fusing a co-inductive co-domain is
F:NNF
F0=f0
F1=f1(F(g0))
F(S(Sn)) = fS(F(gn)) (F(g(Sn)).
4 Evaluating the Prophecies
The relation between Bfand Bis not very clear: since the elements of Bfmay
represent infinite computations, they do not always correspond to elements of
B. Instead, we can find a correspondence between Bfand the type of partial
elements of Bdefined in [8] as:
CoInductive Bν:Typ e
return:BBν
step:BνBν
Following [8], we use the notations bfor (return b)andx for (step x). The
definition above means that an element of Bνcan be either a finite sequence of
steps followed by the return of a value of B, or an infinite sequence of steps.
So Bνrepresents the partial elements of B.
Our goal is then to represent the program fin type theory as a function
with type ABν. To accomplish this, we need to define an evaluation oper-
ator evaluatef:BfBν.NoticethatBfhas a tree structure, since elements
constructed by becorrespond to nodes of branching degree n, while Bνhas a
linear structure given by a sequence of steps. The problem consists in linearis-
ing a tree or, in computational terms, sequentialising a parallel computation. To
achieve this, we create a stack of calls and we execute them sequentially. Every
call, when evaluated, can in turn generate new calls that are added to the stack.
The stack is represented by a vector. The empty vector is denoted by .We
use the notation x1,...,x
n;
vto denote the vector whose first nelements are
x1,...,x
nand whose elements from the (n+1)th on are given by the vector
v.
In the case where
vis the empty vector, we simply write x1,...,x
n.Inwhat
follows, Akrepresents the type of vectors of elements in Awith length k.
76 A. Bove and V. Capretta
The evaluation operator also has an extra parameter: a function that will
compute the final result from the results of the recursive calls on the elements
in the stack. This is similar to continuation-passing programming [13].
The co-recursive evaluation function θf, defined below, performs the sequen-
tialisation we just mentioned. The function is defined by cases on the length of
the vector and, when the vector is not empty, by cases on its first element.
θf:(k:N)(Bf)k(BkB)Bν
θf0h=h
···
θf(Sk)(be
xy1···yn);
vh=(θf(n+k)y1,...,y
n;
vh)
where hz1,...,z
n;
u=he[z1,...,z
n];
u
···
Notice that the recursive call in the function θfare guarded by the constructor
, hence this is a valid co-fixpoint definition.
In our running example for the function Fwe obtain:
θF:(k:N)(NF)k(NkN)Nν
θF0h=h
θF(Sk)f0;
vh=(θFk
vh
)
where h
u=ha;
u
θF(Sk)(f1y);
vh=(θF(Sk)y;
vh)
where hz;
u=h(b+cz);
u
θF(Sk)(fSy1y2);
vh=(θF(2 + k)y1,y
2;
vh)
where hz1,z
2;
u=h(z1+z2);
u
The evaluation function, both in its general form and its instantiation for our
example, is defined as follows:
evaluatef:BfBν
evaluatefy=θf1y(λz.z)evaluateF:NFNν
evaluateFy=θF1y(λz.z)
where λz.z denotes the function giving the only element of a vector of length
one.
Finally, we define the desired functions fand F:
f:ABν
fx=evaluatef(fx)F:NNν
Fn=evaluateF(Fn).
5 Validity of the Prophecy Method
We want to prove that the formal version of the function fdefined with the
prophecy method is a correct implementation of the informal recursive function.
Specifically, we want to prove the validity of the equations defining the function.
Remember that fmay return an element consisting of infinite computation
steps when applied to certain inputs. The inductive relation (defined in [8])
Computation by Prophecy 77
Value :AνAProp, for which we use the notation ( ), characterises ter-
minating computations. The expression (xa) states that the element xof Aν
converges to the value ain A. Its inductive definition has two rules:
aa
xa
xa.
We now formulate the recursive equations in terms of ( ) and we prove
that our implementation of the function satisfies them.
For each non-recursive equation fp=ain the informal definition of f,where
amay contain occurrences of the variables in Γbut no recursive calls to f,we
would like to show that the formal version of fsatisfies
x:Γ, f p a;
where
xare the variables defined in the context Γ, and for each recursive
equation of the form fp=e[(fp
1),...,(fp
n)] in the informal definition of f,
we would like to show that its formalisation is such that
x:Γ, r1,...,r
n:B,(fp
1)r1···(fp
n)rn(fp)e[r1,...,r
n].
For our example function F, we want to prove the following three statements
(F0) a,
m:N,(F(g0)) m(F1) (b+cm),
n, m1,m
2:N,(F(gn)) m1(F(g(Sn))) m2
(F(S(Sn)))) (m1+m2).
On the road to proving these results, let us consider more closely the meaning
of prophecies. A prophecy can be seen as the tree representation of the compu-
tation of the result of an expression. That is, it would be the computation trace,
if parallel evaluation were allowed. For example the prophecy
be
xy1···yn
specifies a parallel computation in which we first evaluate the subtrees y1,...,y
n
and, if all these computations terminate giving r1,...,r
nas result, respectively,
then we obtain the output by computing the expression e[r1,...,r
n].
Recall that, since types of partial elements like Bνrepresent computations in
a sequential model, we could not directly define the evaluation of a prophecy fol-
lowing the above intuition, but we needed to use the sequentialising operator θf.
We can characterise the behaviour of (θfk
vh) as follows:
(evaluatefvi) converges for every prophecy viin the vector
v:(Bf)k
if and only if (θfk
vh) converges; moreover, in case they converge, if
zi:Bis the value of (evaluatefvi)for0ik,then(hz1,...,z
k)is
the value of (θfk
vh).
78 A. Bove and V. Capretta
The characterisation of θfis described in the following lemma, where the
inductive relation (
v
u)expressesthat(evaluatefvi)uifor 0 ik,
where viis the ith element of
v:(Bf)kand uiis the ith element of
u:Bk.
Lemma 1
k:N,
v:(Bf)k,h:BkB, b:B,
(θfk
vh)b←→
u:Bk,(
v
u)(h
u=b).
In order to prove Lemma 1 we define a weight on prophecies and vectors of
prophecies. Intuitively, the weight of a finite prophecy indicates the size of the
prophecy. The weight of a prophecy, when defined, must be a positive natural
number. Moreover, the weight of a tree-structured prophecy ywill only be defined
if the weights of all its children are defined. In addition, the weight of yhas to
be strictly greater than the sum of the weights of its children.
Since prophecies need not be well-founded trees, it is not possible to define
their weights by a total function. Instead, the weight of a prophecy is defined
as an inductive relation Wght :BfNProp with a constructor for each
constructor in the set of prophecies. For each constant constructor b:Bf,there
is a weight constructor of the form
wghtb:Wght b 1,
and for each non-constant constructor be:Γe
ntimes

Bf···BfBf,thereis
a weight constructor of the form
x:Γeh1:Wght y1w1··· hn:Wght ynwn
wghtbe
xh1···hn:Wght (be
xy1···yn)(S(w1+···+wn)).
The weight of a vector of prophecies is the sum of the weights of its elements
plus its length, and it is given by an inductive relation
Weight :(k:N)(Bf)kNProp defined as follows:
weight0:Weight 0 0
hy:Wght yw
yhv:Weight k
vw
v
weightSkh
yhv:Weight (Sk)y;
v(S(wy+wv)).
The statement of Lemma 1 can now be restrained to those vectors of prophe-
cies that have a weight. This makes it easier to prove the lemma by applying
course-of-value induction on the weight of the vector. Later, in lemmas 3 and 5,
we show that the restriction can be relaxed because all converging prophecies
have a weight.
Lemma 2
w:N,k:N,
v:(Bf)k,Weight k
vw
h:BkB,b:B, (θfk
vh)b←→
u:Bk,(
v
u)(h
u=b).
Computation by Prophecy 79
Proof. By course-of-value induction on the weight wand cases on k. Recall that
the value of kdetermines the structure of the vector v.Whenvis not empty, we
also perform cases on its first element.
If k=0,then
v=. By definition of θf,wehave(θf0h)=h
and, therefore, it must be that b=(h)and
u=. Hence, the statement is
true.
If k=(Sk)then
v=y;
v. We now perform case analysis on y.
Let ybe a leaf. We know that the vector
vmust have a weight wand
moreover, wmust be strictly smaller than w,w<w. Both directions of the
lemma can now be easily proved by induction hypothesis on the weight w,and
by definition of the functions θfand evaluatef.
Let yhave a tree structure, that is, y=(be
xy1···yn). Given h, by definition
of θfwe get
θf(Sk)(be
xy1···yn);
vh=(θf(n+k)y1,...,y
n;
vh)
with (hz1,...,z
n;
u)=he[z1,...,z
n];
u. Hence, for any given b,wehave
the equivalence
(θf(Sk)
vh)b←→ (θf(n+k)y1,...,y
n;
vh)b. (1)
The new vector of prophecies has a smaller weight than the original one, since
we replaced the first element in the vector by all its children. That is, there is a
weight wsuch that (Weight (n+k)y1,...,y
n;
vw)andw<w. Therefore
we can apply the induction hypothesis to w,h
and band obtain that
(θf(n+k)y1,...,y
n;
vh)b←→
∃z1,...,z
n;
u:Bn+k,(y1,...,y
n;
vz1,...,z
n;
u)
(hz1,...,z
n;
u=b).
(2)
In addition, the weight of y1,...,y
nis strictly smaller than the weight of the
vector
v, so we can apply the inductive hypothesis again with the continuation
h=λz1,...,z
n.e[z1,...,z
n]toobtain
b:B, (θfny1,...,y
n(λz1,...,z
n.e[z1,...,z
n])) b←→
z:Bn,(y1,...,y
n
z)((λz1,...,z
n.e[z1,...,z
n])
z=b).
(3)
Now we prove the main statement.
In the direction from left to right, let us assume (θf(Sk)
vh)b. By the
equivalence in (1), we have that (θf(n+k)y1,...,y
n;
vh)b. Now, by
the instantiated induction hypothesis in (2), we know that there exists a vector
z1,...,z
n;
uwith the stated properties. In particular, (evaluatefyi)zifor
0in, and hence y1,...,y
nz1,...,z
n.
Let z=e[z1···zn]; we claim that z;
uis the vector satisfying the conclusion
of the the lemma. We need to prove that
(y;
vz;
u)(hz;
u=b),
80 A. Bove and V. Capretta
which amounts to proving that (evaluatefy)z, since the rest follows from the
equivalence in (2). By definition of evaluatef, we need to prove that
(θf1(be
xy
1···yn)(λz.z)) e[z1···zn].
By unfolding the definition of θf, we obtain that this statement is equivalent to
the following:
(θfny1,...,y
n(λz1,...,z
n.e[z1,...,z
n])) e[z1···zn].(4)
We now instantiate (3) with b=e[z1···zn], and we apply the right-to-left
direction of the resulting equivalence with the vector z1,...,z
nand the corre-
sponding proofs of the needed hypotheses. We obtain then a proof of the claim
in (4).
In the direction from right to left, assume that
∃z;
u:Bk,(y;
vz;
u)(hz;
u=b).
Then (evaluatefy)zand, since y=(be
xy
1···yn), by the definitions of
evaluatefand θf, we can apply the left-to-right direction of (3) with b=z.Thus,
there exists a vector z1,...,z
nsuch that (evaluatefyi)zifor 0 in,and
e[z1···zn]=z.
We can now use the right-to-left direction of (2) with the vector
z1,...,z
n;
uand the corresponding proofs of the needed hypotheses.
Finally, the equivalence in (1) allows us to conclude that
(θf(Sk)y;
vh)b.
In the next three lemmas, we show that all converging prophecies have a weight.
This allows us to eliminate the weight constraint in Lemma 2, which in turn,
easily allows us to obtain a proof of Lemma 1.
Lemma 3
k:N,
v:(Bf)k,h:BkB, b:B,
(θfk
vhb)→∃w, Weight k
vw.
Proof. By induction on the structure of the proof of (θfk
vh)b,andby
cases on the vector and, when the vector is not empty, on its first element.
Lemma 4
y:Bf,b:B,(evaluatefy)b→∃w, Wght yw.
Proof. By definition of the operator evaluatefand Lemma 3.
Lemma 5
k:N,
v:(Bf)k,
u:(B)k,(
v
u)→∃w, Weight k
vw.
Computation by Prophecy 81
Proof. By induction on k, using Lemma 4 on each of the elements in the vec-
tor
v.
Finally, we are in the position of proving the validity of the equations defining
the function f. Proving the validity of non-recursive equations is immediate: we
only need to reduce the functions fand then evaluatefto obtain the desired
result. The validity of the recursive equations can be proved by using Lemma 1.
Theorem 1 (Validity of Recursive Equations)
x:Γ, r1,...,r
n:B,(fp
1)r1···(fp
n)rn(fp)e[r1,...,r
n].
Proof. Assume that (fp
i)ri,for1in. By definition of fthis means that
evaluatef(fpi)ri. Unfolding definitions, we have that:
fp=evaluatef(fp)
=θf1(fp)(λz.z)
=θf1be
x(fp1)···(fpn)(λz.z)
=(θfn(fp1),···,(fpn)λz1,...,z
n.e[z1,...,z
n]).
The conclusion easily follows now by applying the second constructor of the
inductive relation ( ) and the right-to-left direction of Lemma 1.
In the specific case of the function F, Theorem 1 gives the validity of the equations
presented in page 77.
When reasoning about recursive functions, an inversion principle given by the
converse of Theorem 1 may be useful.
Theorem 2 (Inversion Principle for Recursive Equations)
x:Γ, b:B,(fp)b
r1,...,r
n:B,(fp
1)r1∧···(fp
n)rnb=e[r1,...,r
n].
Proof. By the left-to-right direction of Lemma 1.
6 Conclusions
This article describes a new method to represent (partial) recursive functions in
type theory. It combines ideas from our previous work on the subject, namely,
the one characterising the inputs on which a function terminates by an induc-
tive (domain) predicate [6,4,7], and the one implementing recursive functions by
co-recursion on co-inductive types of partial elements [8].
Given the recursive equations for a computable function f:AB, we define
a co-inductive set Bfof prophecies representing the traces of the computation
of the function. This set is the dual of the predicate defining the domain of
the function as described in [6]. It is easy to define a formal recursive function
f:ABfreturning prophecies as output. The type-theoretic version of the
82 A. Bove and V. Capretta
original function is then a function whose co-domain is the set Bνof partial
elements as studied in [8]. This function is defined by linearising the prophecy
obtained from the formal recursive function f. The linearisation is done by an
operator θfwith two parameters: a stack of recursive calls and a continuation
function that will compute, when possible, the final result.
We prove that a function formalised in type theory with this new method
satisfies all the equations (recursive or not) of its informal version.
We illustrate the method on a toy example, a generalisation Fof the Fibonacci
function. The development for Fhas been fully formalised in the proof assistant
Coq [14,3]. In addition, we also performed a complete formalisation of the quick-
sort algorithm following this method, and of the proofs stating the validity of the
equations for the algorithm. The files of both formalisations are available on the
web at the address: http://www.cs.ru.nl/~venanzio/Coq/prophecy.html.
At the moment, the method has been tested just on simple recursive programs,
that is, not nested or mutually recursive. The formalisation of mutually recursive
functions usually presents no major problems in systems like Coq, but on the
other hand, nested functions are not trivial to formalise. Already our previous
work (using the domain predicates) on nested recursive functions [5] could not
directly be translated into Coq because the proof assistant lacks support for
inductive-recursive definitions, as described by Dybjer in [10].
As can be seen from the proofs, the method is general and can be adapted to
every simple recursive program. However, we have yet to formalise the mecha-
nisation process and therefore, the user must go through the tedious but trivial
process of adapting definitions and proofs. It would be desirable, in a future
stage, to fully automatise the definitions of the set of prophecies, of the function
θf, and the related proofs from the set of (recursive) equations given by the user.
As mentioned before, this technique has several advantages over the method
we have previously developed via a special-purpose accessibility (domain) predi-
cate [6,4,7]; namely, there is no need of extra logical arguments in the definition
of the recursive function; the function can be applied to any element in its do-
main, regardless of termination properties; we obtain a type of partial recursive
functions between any two given types; and composition of recursive functions
can be easily defined through the usual composition of monadic function (see [8]
for further reading on this point).
References
1. Balaa, A., Bertot, Y.: Fonctions ecursives en´erales par it´eration en th´eorie des
types. Journ´ees Francophones des Langages Applicatifs - JFLA02, INRIA (January
2002)
2. Barthe, G., Courtieu, P.: Efficient reasoning about executable specifications in Coq.
In: Carre˜no, V.A., Mu˜noz, C.A., Tahar, S. (eds.) TPHOLs 2002. LNCS, vol. 2410,
pp. 20–23. Springer, Heidelberg (2002)
3. Bertot, Y., Cast´eran, P.: Interactive Theorem Proving and Program Development.
Coq’Art: The Calculus of Inductive Constructions. Springer, Berlin Heidelberg
(2004)
Computation by Prophecy 83
4. Bove, A.: General recursion in type theory. In: Geuvers, H., Wiedijk, F. (eds.)
TYPES 2002. LNCS, vol. 2646, pp. 39–58. Springer, Heidelberg (2003)
5. Bove, A., Capretta, V.: Nested general recursion and partiality in type theory. In:
Boulton, R.J., Jackson, P.B. (eds.) TPHOLs 2001. LNCS, vol. 2152, pp. 121–135.
Springer, Heidelberg (2001)
6. Bove, A., Capretta, V.: Modelling general recursion in type theory. Mathematical
Structures in Computer Science 15(4), 671–708 (2005)
7. Bove, A., Capretta, V.: Recursive functions with higher order domains. In: Urzy-
czyn, P. (ed.) TLCA 2005. LNCS, vol. 3461, pp. 116–130. Springer, Heidelberg
(2005)
8. Capretta, V.: General recursion via coinductive types. Logical Methods in Com-
puter Science 1(2), 1–18 (2005)
9. Capretta, V., Uustalu, T., Vene, V.: Recursive coalgebras from comonads. Infor-
mation and Computation 204(4), 437–468 (2006)
10. Dybjer, P.: A general formulation of simultaneous inductive-recursive definitions
in type theory. Journal of Symbolic Logic, vol. 65(2) (2000)
11. Gim´enez, E.: Codifying guarded definitions with recursive schemes. In: Smith, J.,
Dybjer, P., Nordstr¨om, B. (eds.) TYPES 1994. LNCS, vol. 996, pp. 39–59. Springer,
Heidelberg (1995)
12. McBride, C., McKinna, J.: The view from the left. Journal of Functional Program-
ming 14(1), 69–111 (2004)
13. Reynolds, J.C.: The discoveries of continuations. Lisp. and Symbolic Computa-
tion 6(3–4), 233–248 (1993)
14. The Coq Development Team. LogiCal Project. The Coq Proof Assistant. Reference
Manual. Version 8. INRIA (2004) Available at the web page
http://pauillac.inria.fr/coq/coq-eng.html
... Obj.magic : ∀ α β, α → β 1.1. CONTEXT 5 App Γ e 1 : A → B Γ e 2 : A Γ e 1 e 2 : B interactions with the outer world. For example, a JavaScript program in a web page is sealed and should not be able to access to the le system of the client, whereas a Unix shell script must have access to the local le system. ...
... Previous works [30,5] have exposed several advantages and weaknesses of proof by reection, especially in comparison with the traditional LCF proof style [28]. In a nutshell, the former is considered more robust to change, while the latter is easier to write. ...
... The monad takes a state and returns a new state plus a value of type α if the computation is successful, or an error message in case of failure. We implement the state as a dependent record containing: 5 The plugin Cybele is available under MIT license on cybele.gforge.inria.fr. 6 In this work, we are not interested in a ne grain control of eects so we provide only one monad with all the eectful operations we found useful. ...
Thesis
In this thesis, we develop new techniques to conveniently write formally verified programs. To proceed, we study the use of Coq as a programming language in different settings. Coq being a purely functional language, we mainly focus on the representation and on the specification of impure effects, like exceptions, mutable references, inputs-outputs, and concurrency.First, we work on two preliminary projects helping us to understand the challenges of programming in Coq. The first project, Cybele, is a Coq plugin to write efficient proofs by reflection with effects. We compile and execute the impure effects in OCaml to generate a prophecy, a kind of certificate, and then interpret the effects in Coq using the prophecy. The second project, the compiler CoqOfOCaml, imports OCaml programs with effects into Coq, using an effect inference system.Next, we describe different generic and composable representations of impure effects in Coq. The breakable computations combine the standard exceptions and mutable references effects, with a pause mechanism to make explicit the evaluation steps in order to represent the concurrent evaluation of two terms. By implementing the Pluto web server in Coq, we realize that the most important effects to program are the asynchronous inputs-outputs. Indeed, these effects are ubiquitous and cannot be encoded in a purely functional manner. Thus, we design the asynchronous computations as a first way to represent and compile programs with events and handlers in Coq.Then, we study techniques to prove properties about programs with effects. We start with the verification of the blog system ChickBlog written in the language of the interactive computations. This blog runs one worker with synchronous inputs-outputs per client. We verify our blog using the method of specification by use cases. We adapt this technique to type theory by expressing a use case as a well-typed co-program over the program we verify. Thanks to this formalism, we can present a use case as a symbolic test program and symbolically debug it, step by step, using the interactive proof mode of Coq. To our knowledge, this is the first such adaptation of the use case specifications in type theory. We believe that the formal specification by use cases is one of the keys to verify effectful programs, as the method of use cases proved to be convenient to express (informal) specifications in the software industry. We extend our formalism to concurrent and potentially non-terminating programs with the language of concurrent computations. Apart from the use case method, we design a model-checker to verify the deadlock freedom of concurrent computations, by compiling the parallel composition to the non-deterministic choice operator using the language of blocking computations.
... Prophecies in Type Theory. Several works propose [5,14] methods to define and to reason on general recursive functions in Type Theory. Bove and Capretta [5] formally define a notion of prophecy, a coinductive predicate derived from a set of non-overlaping recursive equations characterizing the co-domain of the partial function defined by these equations. ...
... Several works propose [5,14] methods to define and to reason on general recursive functions in Type Theory. Bove and Capretta [5] formally define a notion of prophecy, a coinductive predicate derived from a set of non-overlaping recursive equations characterizing the co-domain of the partial function defined by these equations. Our prophecies and Bove and Capretta's share the same role of prediction. ...
Conference Paper
Full-text available
Proof-by-reflection is a well-established technique that employs decision procedures to reduce the size of proof-terms. Currently, decision procedures can be written either in Type Theory—in a purely functional way that also ensures termination— or in an effectful programming language, where they are used as oracles for the certified checker. The first option offers strong correctness guarantees, while the second one permits more efficient implementations. We propose a novel technique for proof-by-reflection that marries, in Type Theory, an effectful language with (partial) proofs of correctness. The key to our approach is to use simulable monads, where a monad is simulable if, for all terminating reduction sequences in its equivalent effectful computational model, there exists a witness from which the same reduction may be simulated a posteriori by the monad. We encode several examples using simulable monads and demonstrate the advantages of the technique over previous approaches.
... The function itself is formalised by giving it an extra type argument, a proof that the input values satisfy the domain predicate for the function, and it is defined by structural recursion on this proof. In our second approach [9, 6], we associate to each data type a coinductive type of partial elements. Computations are directly modelled by (possible) infinite structures. ...
... Alternatively, we could work with a hierarchy of universes and accept that we are not able to formalise all recursive function definitions. In [9, 6], we need support for coinductive definitions in order to obtain the type of partial functions. ...
Conference Paper
Full-text available
Our goal is to define a type of partial recursive functions in constructive type theory. In a series of previous articles, we studied two different formulations of partial functions and general recursion. We could obtain a type only by extending the theory with either an impredicative universe or with coinductive definitions. Here we present a new type constructor that eludes such entities of dubious constructive credentials. We start by showing how to break down a recursive function definition into three components: the first component generates the arguments of the recursive calls, the second evaluates them, and the last computes the output from the results of the recursive calls. We use this dissection as the basis for the introduction rule of the new type constructor. Every partial recursive function is associated with an inductive domain predicate; evaluation of the function requires a proof that the input values satisfy the predicate. We give a constructive justification for the new construct by interpreting it into the base type theory. This shows that the extended theory is consistent and constructive.
... For example, Dijkstra [2012] presents an experience report of automatically translating Haskell to Coq. In order to model partial function definitions Dijkstra uses a method by Bove and Capretta [2007]. This method extends functions with an additional argument, which proves certain invariants about all function applications. ...
Conference Paper
We show how various Haskell language features that are related to ambient effects can be modeled in Coq. For this purpose we build on previous work that demonstrates how to reason about existing Haskell programs by translating them into monadic Coq programs. A model of Haskell programs in Coq that is polymorphic over an arbitrary monad results in non-strictly positive types when transforming recursive data types likes lists. Such non-strictly positive types are not accepted by Coq's termination checker. Therefore, instead of a model that is generic over any monad, the approach we build on uses a specific monad instance, namely the free monad in combination with containers, to model various kinds of effects. This model allows effect-generic proofs. In this paper we consider ambient effects that may occur in Haskell, namely partiality, errors, and tracing, in detail. We observe that, while proving propositions that hold for all kinds of effects is attractive, not all propositions of interest hold for all kinds of effects. Some propositions fail for certain effects because the usual monadic translation models call-by-name and not call-by-need. Since modeling the evaluation semantics of call-by-need in the presence of effects like partiality is complex and not necessary to prove propositions for a variety of effects, we identify a specific class of effects for which we cannot observe a difference between call-by-name and call-by-need. Using this class of effects we can prove propositions for all effects that do not require a model of sharing.
... The constant ó and the type constructor P are unusual with respect to the traditional monadic extensions of the lambda calculus. They are inspired in the notions of compilation and certificates [22,24]. Any proposal of simulable monad M must include the definition of the compilation of its effectful primitives and show the fulfilment of the requirements. ...
Thesis
Full-text available
La programmation certifiée offre un cadre dans lequel tout programme est correct par construction. Les assistants de preuve et les langages de programmation avec types dépendents sont les représentants de ce paradigme, où la prévue et l’implementation d’un programme sont faites au même temps. Toutefois, il existe certaines limitations : un programme écrit en théorie des types est construit seulement avec des fonctions pures et totales.Notre objectif est d’écrire des programmes efficaces et certifiés. Les contributions de cette thèse sont la formalisation, dans le lambda calcul simplement typé, de deux mécanismes pour améliorer l’efficacité : la validation des calculs impurs et l’optimisation des calculs incrémentaux.Un calcul impur, c’est-à-dire un programme avec effets, et sa validation dans un langage fonctionnel et total est fait á l’aide d’une simulation a posteriori. La simulation est effectuée après, par une procédure monadique et elle est guidée par une prophétie. Un oracle efficace est responsable de la production des prophéties et lui est en fait, la procédure monadique traduite dans un language de programmation généraliste.La deuxième contribution est une optimisation pour les calculs incrémentaux. L’incrémentalité consiste à propager des changements des entrées en changements des sorties, elle est guidée par les descriptions formelles du changement des termes et une différenciation dynamique des fonctions. La représentation des changements de données est pris en charge par les types déplaçables et une extension du lambda calcul simplement typé avec dérivées et dérivées partielles offre un language pour raisonner sur l’incrementalité.
... Capretta proves that all recursive functions can be represented in this way, but they often require a rather unnatural manipulation. In order to simplify definitions in Capretta's model, Bove and Capretta (2007) suggest an approach that introduces an intermediate coinductive type characterising the computation structure which is-unlike the monad above-specific to the individual function. This intermediate tree-shaped structure is called a prophecy and it can be seen as the dual to the inductive domain predicate. ...
Article
Full-text available
The use of interactive theorem provers to establish the correctness of critical parts of a software development or for formalizing mathematics is becoming more common and feasible in practice. However, most mature theorem provers lack a direct treatment of partial and general recursive functions; overcoming this weakness has been the objective of intensive research during the last decades. In this article, we review several techniques that have been proposed in the literature to simplify the formalization of partial and general recursive functions in interactive theorem provers. Moreover, we classify the techniques according to their theoretical basis and their practical use. This uniform presentation of the different techniques facilitates the comparison and highlights their commonalities and differences, as well as their relative advantages and limitations. We focus on theorem provers based on constructive type theory (in particular, Agda and Coq) and higher-order logic (in particular Isabelle/HOL). Other systems and logics are covered to a certain extent, but not exhaustively. In addition to the description of the techniques, we also demonstrate tools which facilitate working with the problematic functions in particular theorem provers.
... The disadvantage is that there is no general type of partial recursive functions, but instead each function has its own private type of the form σ → dom f σ → τ . Either impredicativity [13] or a coinductive construction [14] can be used to overcome this. Note that in our simply-typed framework this is not an issue, since partial functions are just underspecified total functions (of type σ → τ ). ...
Article
Based on inductive definitions, we develop a tool that automates the definition of partial recursive functions in higher-order logic (HOL) and provides appropriate proof rules for reasoning about them. Termination is modeled by an inductive domain predicate which follows the structure of the recursion. Since a partial induction rule is available immediately, partial correctness properties can be proved before termination is established. It turns out that this modularity also facilitates termination arguments for total functions, in particular for nested recursions. Our tool is implemented as a definitional package extending Isabelle/HOL. Various extensions provide convenience to the user: pattern matching, default values, tail recursion, mutual recursion and currying.
... We give a rather detailed survey of those ideas in the related work section of a previous paper [6]. Since the publication of that article, there have been a couple of papers that use co-inductive types to model partiality [9] [7], and a suggestion to extend type theory with a type of partial recursive functions [8]. See the introduction section of this last article for a survey of other approaches to defining a type of partial functions in type theory. ...
Article
Full-text available
Bove and Capretta have presented a method to deal with partial and general recursive functions in constructive type theory which relies on an inductive characterisation of the domains of the functions. The method separates the logical and the computational aspects of an algorithm, and facilitates the formal verification of the functions being defined. For nested recursive functions, the method uses Dybjer' schema for simultaneous inductive-recursive definitions. However, not all constructive type theories support this kind of definitions.Here we present a new approach for dealing with partial and general recursive functions that preserves the advantages of the method by Bove and Capretta, but which does not rely on inductive-recursive definitions. In this approach, we start by inductively defining the graph of the function, from which we first define the domain and afterwards the type-theoretic version of the function. We show two ways of proving the formal specification of the functions defined with this new approach: by induction on the graph, or by using an induction principle in the style of the induction principle associated to the domain predicates of the Bove-Capretta method.
... We have seen two different realisations of a type A ⇀ B of partial computable functions between types A and B. The first implements them as functions on a domain characterised by an inductive predicate; the second implements them as total functions returning a coinductively defined partial element. A bridge between the two techniques consists in defining a coinductive version of the domain predicate, whose elements are the traces of all computations, including the diverging ones: The paper [16] gives the theory behind coinductive computation traces and its relation with other methods to represent recursive functions. ...
Article
Full-text available
This is a survey article on the use of coalgebras in functional programming and type theory. It presents the basic theory underlying the implementation of coinductive types, families and predicates. It gives an overview of the application of corecursive methods to the study of general recursion, formal power series, tabulations of functions on inductive data. It also sketches some advanced topics in the study of the solutions to non-guarded corecursive equations and the design of non-standard type theory.
Article
We propose to use the Knaster-Tarski least fixed point theorem as a basis to define recursive functions in the Calculus of Inductive Constructions. This widens the class of functions that can be modelled in type-theory based theorem proving tools to potentially non-terminating functions. This is only possible if we extend the logical framework by adding some axioms of classical logic. We claim that the extended framework makes it possible to reason about terminating or non-terminating computations and we show that extraction can also be extended to handle the new functions.
Article
Full-text available
The concept of recursive coalgebra of a functor was introduced in the 1970s by Osius in his work on categorical set theory to discuss the relationship between wellfounded induction and recursively specified functions. In this paper, we motivate the use of recursive coalgebras as a paradigm of structured recursion in programming semantics, list some basic facts about recursive coalgebras and, centrally, give new conditions for the recursiveness of a coalgebra based on comonads, comonad-coalgebras and distributive laws of functors over comonads. We also present an alternative construction using countable products instead of cofree comonads.
Conference Paper
Full-text available
We extend Bove's technique for formalising simple general recursive algorithms in constructive type theory to nested recursive algorithms. The method consists in defining an inductive special-purpose accessibility predicate, that characterizes the inputs on which the algorithm terminates. As a result, the type-theoretic version of the algorithm can be defined by structural recursion on the proof that the input values satisfy this predicate. This technique results in definitions in which the computational and logical parts are clearly separated; hence, the type-theoretic version of the algorithm is given by its purely functional content, similarly to the corresponding program in a functional programming language. In the case of nested recursion, the special predicate and the type-theoretic algorithm must be defined simultaneously, because they depend on each other. This kind of definitions is not allowed in ordinary type theory, but it is provided in type theories extended with Dybjer's schema for simultaneous inductive-recursive definitions. The technique applies also to the formalisation of partial functions as proper type-theoretic functions, rather than relations representing their graphs.
Conference Paper
Full-text available
We describe a package to reason eciently,about executable specifications in Coq. The package,provides,a command,for synthesizing a customized induction principle for a recursively defined function, and a tactic that combines,the application,of the customized,induction,prin- ciple with,automatic,rewriting. We further illustrate how,the package leads to a drastic reduction,(by a factor of 10 approximately),of the size of the proofs in a large-scale case study on reasoning,about,JavaCard.
Article
We extend Bove's technique for formalising simple general recursive algorithms in constructive type theory to nested recursive algorithms. The method consists in defining an inductive special-purpose accessibility predicate, that characterises the inputs on which the algorithm terminates. As a result, the type-theoretic version of the algorithm can be defined by structural recursion on the proof that the input values satisfy this predicate. This technique results in definitions in which the computational and logical parts are clearly separated; hence, the type-theoretic version of the algorithm is given by its purely functional content, similarly to the corresponding program in a functional programming language. In the case of nested recursion, the special predicate and the type-theoretic algorithm must be defined simultaneously, because they depend on each other. This kind of definitions is not allowed in ordinary type theory, but it is provided in type theories extended wit...
Book
Traduction en chinois parue en 2010. Tsinghua University Press. ISBN 9787302208136
Conference Paper
We formalize an extension of the Calculus of Constructions with inductive and coinductive types which allows a more direct description of recursive definitions. The approach we follow is close to the one proposed for Martin-Lf's type theory in [5]. Recursive objects can be defined by fixed-point definitions as in functional programming languages, and a syntactical checking of these definitions avoids the introduction of non-normalizable terms. We show that the conditions for accepting a recursive definition proposed in [5] are not sufficient for the Calculus of Constructions, and we modify them. As a way of justifying our conditions, we develop a general method to codify a fix point definition satisfying them using well-known recursive schemes, like primitive recursion and co-recursion. We also propose different reduction rules from the ones used in [5] in order to obtain a decidable conversion relation for the system.
Conference Paper
In this work, a method to formalise general recursive algorithms in constructive type theory is presented throughout examples. The method separates the computational and logical parts of the definitions. As a consequence, the resulting type-theoretic algorithms are clear, compact and easy to understand. They are as simple as their equivalents in a functional programming language, where there is no restriction on recursive calls. Given a general recursive algorithm, the method consists in defining an inductive special-purpose accessibility predicate that characterises the inputs on which the algorithm terminates. The type-theoretic version of the algorithm can then be defined by structural recursion on the proof that the input values satisfy this predicate. When formalising nested algorithms, the special-purpose accessibility predicate and the type-theoretic version of the algorithm must be defined simultaneously because they depend on each other. Since the method separates the computational part from the logical part of a definition, formalising partial functions becomes also possible
Article
The concept of recursive coalgebra of a functor was introduced in the 1970s by Osius in his work on categorical set theory to discuss the relationship between wellfounded induction and recursively specified functions. In this paper, we motivate the use of recursive coalgebras as a paradigm of structured recursion in programming semantics, list some basic facts about recursive coalgebras and, centrally, give new conditions for the recursiveness of a coalgebra based on comonads, comonad-coalgebras and distributive laws of functors over comonads. We also present an alternative construction using countable products instead of cofree comonads.