summary |
shortlog |
changelog |
graph |
tags |
bookmarks |
branches |
files |
changeset |
raw | gz |
help

author | lcp |

Fri, 19 Nov 1993 11:31:10 +0100 | |

changeset 130 | c035b6b9eafc |

parent 129 | dc50a4b96d7b |

child 131 | bb0caac13eff |

Many edits suggested by Grundy & Thompson

--- a/doc-src/ind-defs.tex Fri Nov 19 11:25:36 1993 +0100 +++ b/doc-src/ind-defs.tex Fri Nov 19 11:31:10 1993 +0100 @@ -1,9 +1,11 @@ -\documentstyle[11pt,a4,proof,lcp,alltt,amssymbols,draft]{article} +\documentstyle[12pt,a4,proof,lcp,alltt,amssymbols]{article} +%CADE version should use 11pt and the Springer style \newif\ifCADE \CADEfalse -\title{A Fixedpoint Approach to Implementing (Co-)Inductive Definitions\\ - DRAFT\thanks{Research funded by the SERC (grants GR/G53279, +\title{A Fixedpoint Approach to Implementing (Co)Inductive + Definitions\thanks{Jim Grundy and Simon Thompson made detailed comments on + a draft. Research funded by the SERC (grants GR/G53279, GR/H40570) and by the ESPRIT Basic Research Action 6453 `Types'.}} \author{{\em Lawrence C. Paulson}\\ @@ -108,21 +110,22 @@ approach, based on fixedpoint definitions. It is unusually general: it admits all monotone inductive definitions. It is conceptually simple, which has allowed the easy implementation of mutual recursion and other - conveniences. It also handles co-inductive definitions: simply replace + conveniences. It also handles coinductive definitions: simply replace the least fixedpoint by a greatest fixedpoint. This represents the first - automated support for co-inductive definitions. + automated support for coinductive definitions. + + The method has been implemented in Isabelle's formalization of ZF set + theory. It should + be applicable to any logic in which the Knaster-Tarski Theorem can be + proved. The paper briefly describes a method of formalizing + non-well-founded data structures in standard ZF set theory. Examples include lists of $n$ elements, the accessible part of a relation and the set of primitive recursive functions. One example of a - co-inductive definition is bisimulations for lazy lists. \ifCADE\else + coinductive definition is bisimulations for lazy lists. \ifCADE\else Recursive datatypes are examined in detail, as well as one example of a - ``co-datatype'': lazy lists. The appendices are simple user's manuals + {\bf codatatype}: lazy lists. The appendices are simple user's manuals for this Isabelle/ZF package.\fi - - The method has been implemented in Isabelle's ZF set theory. It should - be applicable to any logic in which the Knaster-Tarski Theorem can be - proved. The paper briefly describes a method of formalizing - non-well-founded data structures in standard ZF set theory. \end{abstract} % \begin{center} Copyright \copyright{} \number\year{} by Lawrence C. Paulson @@ -132,7 +135,7 @@ \tableofcontents \cleardoublepage -\pagenumbering{arabic}\pagestyle{headings}\DRAFT +\pagenumbering{arabic}\pagestyle{headings} \section{Introduction} Several theorem provers provide commands for formalizing recursive data @@ -141,7 +144,7 @@ system~\cite{melham89}. Such data structures are called {\bf datatypes} below, by analogy with {\tt datatype} definitions in Standard~ML\@. -A datatype is but one example of a {\bf inductive definition}. This +A datatype is but one example of an {\bf inductive definition}. This specifies the least set closed under given rules~\cite{aczel77}. The collection of theorems in a logic is inductively defined. A structural operational semantics~\cite{hennessy90} is an inductive definition of a @@ -149,30 +152,30 @@ provide commands for formalizing inductive definitions; these include Coq~\cite{paulin92} and again the HOL system~\cite{camilleri92}. -The dual notion is that of a {\bf co-inductive definition}. This specifies +The dual notion is that of a {\bf coinductive definition}. This specifies the greatest set closed under given rules. Important examples include using bisimulation relations to formalize equivalence of processes~\cite{milner89} or lazy functional programs~\cite{abramsky90}. Other examples include lazy lists and other infinite data structures; these -are called {\bf co-datatypes} below. +are called {\bf codatatypes} below. Most existing implementations of datatype and inductive definitions accept -an artifically narrow class of inputs, and are not easily extended. The +an artificially narrow class of inputs, and are not easily extended. The shell principle and Coq's inductive definition rules are built into the underlying logic. Melham's packages derive datatypes and inductive definitions from specialized constructions in higher-order logic. This paper describes a package based on a fixedpoint approach. Least fixedpoints yield inductive definitions; greatest fixedpoints yield -co-inductive definitions. The package is uniquely powerful: +coinductive definitions. The package is uniquely powerful: \begin{itemize} \item It accepts the largest natural class of inductive definitions, namely - all monotone inductive definitions. + all that are provably monotone. \item It accepts a wide class of datatype definitions. -\item It handles co-inductive and co-datatype definitions. Most of - the discussion below applies equally to inductive and co-inductive +\item It handles coinductive and codatatype definitions. Most of + the discussion below applies equally to inductive and coinductive definitions, and most of the code is shared. To my knowledge, this is - the only package supporting co-inductive definitions. + the only package supporting coinductive definitions. \item Definitions may be mutually recursive. \end{itemize} The package is implemented in Isabelle~\cite{isabelle-intro}, using ZF set @@ -182,7 +185,7 @@ transforms these rules into a mapping over sets, and attempts to prove that the mapping is monotonic and well-typed. If successful, the package makes fixedpoint definitions and proves the introduction, elimination and -(co-)induction rules. The package consists of several Standard ML +(co)induction rules. The package consists of several Standard ML functors~\cite{paulson91}; it accepts its argument and returns its result as ML structures. @@ -192,13 +195,13 @@ the Isabelle/ZF theory provides well-founded recursion and other logical tools to simplify this task~\cite{paulson-set-II}. -\S2 briefly introduces the least and greatest fixedpoint operators. \S3 -discusses the form of introduction rules, mutual recursion and other points -common to inductive and co-inductive definitions. \S4 discusses induction -and co-induction rules separately. \S5 presents several examples, -including a co-inductive definition. \S6 describes datatype definitions, -while \S7 draws brief conclusions. \ifCADE\else The appendices are simple -user's manuals for this Isabelle/ZF package.\fi +{\bf Outline.} \S2 briefly introduces the least and greatest fixedpoint +operators. \S3 discusses the form of introduction rules, mutual recursion and +other points common to inductive and coinductive definitions. \S4 discusses +induction and coinduction rules separately. \S5 presents several examples, +including a coinductive definition. \S6 describes datatype definitions, while +\S7 draws brief conclusions. \ifCADE\else The appendices are simple user's +manuals for this Isabelle/ZF package.\fi Most of the definitions and theorems shown below have been generated by the package. I have renamed some variables to improve readability. @@ -210,7 +213,8 @@ \lfp(D,h) & \equiv & \inter\{X\sbs D. h(X)\sbs X\} \\ \gfp(D,h) & \equiv & \union\{X\sbs D. X\sbs h(X)\} \end{eqnarray*} -Say that $h$ is {\bf bounded by}~$D$ if $h(D)\sbs D$, and {\bf monotone} if +Let $D$ be a set. Say that $h$ is {\bf bounded by}~$D$ if $h(D)\sbs D$, and +{\bf monotone below~$D$} if $h(A)\sbs h(B)$ for all $A$ and $B$ such that $A\sbs B\sbs D$. If $h$ is bounded by~$D$ and monotone then both operators yield fixedpoints: \begin{eqnarray*} @@ -225,17 +229,19 @@ This fixedpoint theory is simple. The Knaster-Tarski theorem is easy to prove. Showing monotonicity of~$h$ is trivial, in typical cases. We must also exhibit a bounding set~$D$ for~$h$. Sometimes this is trivial, as -when a set of ``theorems'' is (co-)inductively defined over some previously +when a set of ``theorems'' is (co)inductively defined over some previously existing set of ``formulae.'' But defining the bounding set for -(co-)datatype definitions requires some effort; see~\S\ref{data-sec} below. +(co)datatype definitions requires some effort; see~\S\ref{univ-sec} below. -\section{Elements of an inductive or co-inductive definition}\label{basic-sec} -Consider a (co-)inductive definition of the sets $R_1$, \ldots,~$R_n$, in +\section{Elements of an inductive or coinductive definition}\label{basic-sec} +Consider a (co)inductive definition of the sets $R_1$, \ldots,~$R_n$, in mutual recursion. They will be constructed from previously existing sets $D_1$, \ldots,~$D_n$, respectively, which are called their {\bf domains}. The construction yields not $R_i\sbs D_i$ but $R_i\sbs D_1+\cdots+D_n$, where -$R_i$ is the image of~$D_i$ under an injection~\cite[\S4.5]{paulson-set-II}. +$R_i$ is contained in the image of~$D_i$ under an +injection. Reasons for this are discussed +elsewhere~\cite[\S4.5]{paulson-set-II}. The definition may involve arbitrary parameters $\vec{p}=p_1$, \ldots,~$p_k$. Each recursive set then has the form $R_i(\vec{p})$. The @@ -243,8 +249,8 @@ would appear to be a serious restriction compared with other systems such as Coq~\cite{paulin92}. For instance, we cannot define the lists of $n$ elements as the set $\listn(A,n)$ using rules where the parameter~$n$ -varies. \S\ref{listn-sec} describes how to express this definition using the -package. +varies. \S\ref{listn-sec} describes how to express this set using the +inductive definition package. To avoid clutter below, the recursive sets are shown as simply $R_i$ instead of $R_i(\vec{p})$. @@ -259,17 +265,16 @@ The premise $t\in M(R_i)$ is permitted if $M$ is a monotonic operator on sets, satisfying the rule \[ \infer{M(A)\sbs M(B)}{A\sbs B} \] -The inductive definition package must be supplied monotonicity rules for -all such premises. +The user must supply the package with monotonicity rules for all such premises. Because any monotonic $M$ may appear in premises, the criteria for an acceptable definition is semantic rather than syntactic. A suitable choice of~$M$ and~$t$ can express a lot. The powerset operator $\pow$ is monotone, and the premise $t\in\pow(R)$ expresses $t\sbs R$; see -\S\ref{acc-sec} for an example. The `list of' operator is monotone, and -the premise $t\in\lst(R)$ avoids having to encode the effect of~$\lst(R)$ -using mutual recursion; see \S\ref{primrec-sec} and also my earlier -paper~\cite[\S4.4]{paulson-set-II}. +\S\ref{acc-sec} for an example. The `list of' operator is monotone, as is +easily proved by induction. The premise $t\in\lst(R)$ avoids having to +encode the effect of~$\lst(R)$ using mutual recursion; see \S\ref{primrec-sec} +and also my earlier paper~\cite[\S4.4]{paulson-set-II}. Introduction rules may also contain {\bf side-conditions}. These are premises consisting of arbitrary formulae not mentioning the recursive @@ -286,7 +291,7 @@ \infer{\{a\}\un b\in\Fin(A)}{a\in A & b\in\Fin(A)} \] -The domain for a (co-)inductive definition must be some existing set closed +The domain in a (co)inductive definition must be some existing set closed under the rules. A suitable domain for $\Fin(A)$ is $\pow(A)$, the set of all subsets of~$A$. The package generates the definition \begin{eqnarray*} @@ -295,9 +300,9 @@ \lambda X. \{z\in\pow(A). & z=\emptyset \disj{} \\ &(\exists a\,b. z=\{a\}\un b\conj a\in A\conj b\in X)\}) \end{array} -\end{eqnarray*} +\end{eqnarray*} The contribution of each rule to the definition of $\Fin(A)$ should be -obvious. A co-inductive definition is similar but uses $\gfp$ instead +obvious. A coinductive definition is similar but uses $\gfp$ instead of~$\lfp$. The package must prove that the fixedpoint operator is applied to a @@ -306,12 +311,12 @@ $t\in M(R_i)$ premise, then this proof is trivial.\footnote{Due to the presence of logical connectives in the fixedpoint's body, the monotonicity proof requires some unusual rules. These state that the - connectives $\conj$, $\disj$ and $\exists$ are monotonic with respect to - the partial ordering on unary predicates given by $P\sqsubseteq Q$ if and + connectives $\conj$, $\disj$ and $\exists$ preserve monotonicity with respect + to the partial ordering on unary predicates given by $P\sqsubseteq Q$ if and only if $\forall x.P(x)\imp Q(x)$.} -The result structure returns the definitions of the recursive sets as a theorem -list called {\tt defs}. It also returns, as the theorem {\tt unfold}, a +The result structure contains the definitions of the recursive sets as a theorem +list called {\tt defs}. It also contains, as the theorem {\tt unfold}, a fixedpoint equation such as \begin{eqnarray*} \Fin(A) & = & @@ -320,16 +325,16 @@ &(\exists a\,b. z=\{a\}\un b\conj a\in A\conj b\in \Fin(A))\} \end{array} \end{eqnarray*} -It also returns, as the theorem {\tt dom\_subset}, an inclusion such as +It also contains, as the theorem {\tt dom\_subset}, an inclusion such as $\Fin(A)\sbs\pow(A)$. \subsection{Mutual recursion} \label{mutual-sec} -In a mutually recursive definition, the domain for the fixedoint construction +In a mutually recursive definition, the domain of the fixedpoint construction is the disjoint sum of the domain~$D_i$ of each~$R_i$, for $i=1$, \ldots,~$n$. The package uses the injections of the binary disjoint sum, typically $\Inl$ and~$\Inr$, to express injections -$h_{1,n}$, \ldots, $h_{n,n}$ for the $n$-ary disjoint sum $D_1+\cdots+D_n$. +$h_{1n}$, \ldots, $h_{nn}$ for the $n$-ary disjoint sum $D_1+\cdots+D_n$. As discussed elsewhere \cite[\S4.5]{paulson-set-II}, Isabelle/ZF defines the operator $\Part$ to support mutual recursion. The set $\Part(A,h)$ @@ -341,15 +346,15 @@ $n>1$, the package makes $n+1$ definitions. The first defines a set $R$ using a fixedpoint operator. The remaining $n$ definitions have the form \begin{eqnarray*} - R_i & \equiv & \Part(R,h_{i,n}), \qquad i=1,\ldots, n. + R_i & \equiv & \Part(R,h_{in}), \qquad i=1,\ldots, n. \end{eqnarray*} It follows that $R=R_1\un\cdots\un R_n$, where the $R_i$ are pairwise disjoint. \subsection{Proving the introduction rules} -The uesr supplies the package with the desired form of the introduction +The user supplies the package with the desired form of the introduction rules. Once it has derived the theorem {\tt unfold}, it attempts -to prove the introduction rules. From the user's point of view, this is the +to prove those rules. From the user's point of view, this is the trickiest stage; the proofs often fail. The task is to show that the domain $D_1+\cdots+D_n$ of the combined set $R_1\un\cdots\un R_n$ is closed under all the introduction rules. This essentially involves replacing @@ -367,33 +372,39 @@ specifically proved for a particular inductive definition; sometimes this is the easiest way to get the definition through! -The package returns the introduction rules as the theorem list {\tt intrs}. +The result structure contains the introduction rules as the theorem list {\tt +intrs}. \subsection{The elimination rule} -The elimination rule, called {\tt elim}, is derived in a straightforward -manner. Applying the rule performs a case analysis, with one case for each -introduction rule. Continuing our example, the elimination rule for $\Fin(A)$ -is +The elimination rule, called {\tt elim}, performs case analysis: a +case for each introduction rule. The elimination rule +for $\Fin(A)$ is \[ \infer{Q}{x\in\Fin(A) & \infer*{Q}{[x=\emptyset]} & \infer*{Q}{[x=\{a\}\un b & a\in A &b\in\Fin(A)]_{a,b}} } \] +This rule states that if $x\in\Fin(A)$ then either $x=\emptyset$ or else +$x=\{a\}\un b$ for some $a\in A$ and $b\in\Fin(A)$; it is a simple consequence +of {\tt unfold}. + +\ifCADE\typeout{****Omitting mk_cases from CADE version!}\else The package also returns a function {\tt mk\_cases}, for generating simplified instances of the elimination rule. However, {\tt mk\_cases} only works for datatypes and for inductive definitions involving datatypes, such as an inductively defined relation between lists. It instantiates {\tt elim} with a user-supplied term, then simplifies the cases using the freeness of the underlying datatype. - +See \S\ref{mkcases} for an example. +\fi -\section{Induction and co-induction rules} -Here we must consider inductive and co-inductive definitions separately. +\section{Induction and coinduction rules} +Here we must consider inductive and coinductive definitions separately. For an inductive definition, the package returns an induction rule derived directly from the properties of least fixedpoints, as well as a modified rule for mutual recursion and inductively defined relations. For a -co-inductive definition, the package returns a basic co-induction rule. +coinductive definition, the package returns a basic coinduction rule. \subsection{The basic induction rule}\label{basic-ind-sec} -The basic rule, called simply {\tt induct}, is appropriate in most situations. +The basic rule, called {\tt induct}, is appropriate in most situations. For inductive definitions, it is strong rule induction~\cite{camilleri92}; for datatype definitions (see below), it is just structural induction. @@ -405,8 +416,8 @@ is~$P(t)$. \item The minor premise's eigenvariables are precisely the introduction -rule's free variables that are not parameters of~$R$ --- for instance, $A$ -is not an eigenvariable in the $\Fin(A)$ rule below. +rule's free variables that are not parameters of~$R$. For instance, the +eigenvariables in the $\Fin(A)$ rule below are $a$ and $b$, but not~$A$. \item If the introduction rule has a premise $t\in R_i$, then the minor premise discharges the assumption $t\in R_i$ and the induction @@ -417,7 +428,8 @@ occurrence of $P$ gives the effect of an induction hypothesis, which may be exploited by appealing to properties of~$M$. \end{itemize} -The rule for $\Fin(A)$ is +The induction rule for $\Fin(A)$ resembles the elimination rule shown above, +but includes an induction hypothesis: \[ \infer{P(x)}{x\in\Fin(A) & P(\emptyset) & \infer*{P(\{a\}\un b)}{[a\in A & b\in\Fin(A) & P(b)]_{a,b}} } \] @@ -452,37 +464,42 @@ relations. It eliminates the need to express properties of $z_1$, \ldots,~$z_m$ as properties of the tuple $\pair{z_1,\ldots,z_m}$. -\subsection{Co-induction}\label{co-ind-sec} -A co-inductive definition yields a primitive co-induction rule, with no +\subsection{Coinduction}\label{coind-sec} +A coinductive definition yields a primitive coinduction rule, with no refinements such as those for the induction rules. (Experience may suggest -refinements later.) Consider the co-datatype of lazy lists as an example. For +refinements later.) Consider the codatatype of lazy lists as an example. For suitable definitions of $\LNil$ and $\LCons$, lazy lists may be defined as the greatest fixedpoint satisfying the rules \[ \LNil\in\llist(A) \qquad \infer[(-)]{\LCons(a,l)\in\llist(A)}{a\in A & l\in\llist(A)} \] -The $(-)$ tag stresses that this is a co-inductive definition. A suitable +The $(-)$ tag stresses that this is a coinductive definition. A suitable domain for $\llist(A)$ is $\quniv(A)$, a set closed under variant forms of sum and product for representing infinite data structures -(\S\ref{data-sec}). Co-inductive definitions use these variant sums and +(see~\S\ref{univ-sec}). Coinductive definitions use these variant sums and products. The package derives an {\tt unfold} theorem similar to that for $\Fin(A)$. Then it proves the theorem {\tt co\_induct}, which expresses that $\llist(A)$ is the greatest solution to this equation contained in $\quniv(A)$: -\[ \infer{a\in\llist(A)}{a\in X & X\sbs \quniv(A) & +\[ \infer{x\in\llist(A)}{x\in X & X\sbs \quniv(A) & \infer*{z=\LNil\disj \bigl(\exists a\,l.\, \begin{array}[t]{@{}l} z=\LCons(a,l) \conj a\in A \conj{}\\ l\in X\un\llist(A) \bigr) \end{array} }{[z\in X]_z}} \] +This rule complements the introduction rules; it provides a means of showing +$x\in\llist(A)$ when $x$ is infinite. For instance, if $x=\LCons(0,x)$ then +applying the rule with $X=\{x\}$ proves $x\in\llist(\nat)$. Here $\nat$ +is the set of natural numbers. + Having $X\un\llist(A)$ instead of simply $X$ in the third premise above represents a slight strengthening of the greatest fixedpoint property. I -discuss several forms of co-induction rules elsewhere~\cite{paulson-coind}. +discuss several forms of coinduction rules elsewhere~\cite{paulson-coind}. -\section{Examples of inductive and co-inductive definitions}\label{ind-eg-sec} +\section{Examples of inductive and coinductive definitions}\label{ind-eg-sec} This section presents several examples: the finite set operator, lists of $n$ elements, bisimulations on lazy lists, the well-founded part of a relation, and the primitive recursive functions. @@ -500,7 +517,7 @@ "[| a: A; b: Fin(A) |] ==> cons(a,b) : Fin(A)"]; val monos = []; val con_defs = []; - val type_intrs = [empty_subsetI, cons_subsetI, PowI] + val type_intrs = [empty_subsetI, cons_subsetI, PowI]; val type_elims = [make_elim PowD]); \end{ttbox} The parent theory is obtained from {\tt Arith.thy} by adding the unary @@ -536,10 +553,11 @@ val rec_doms = [("listn", "nat*list(A)")]; val sintrs = ["<0,Nil> : listn(A)", - "[| a: A; <n,l> : listn(A) |] ==> <succ(n), Cons(a,l)> : listn(A)"]; + "[| a: A; <n,l> : listn(A) |] ==> + <succ(n), Cons(a,l)> : listn(A)"]; val monos = []; val con_defs = []; - val type_intrs = nat_typechecks@List.intrs@[SigmaI] + val type_intrs = nat_typechecks @ List.intrs @ [SigmaI]; val type_elims = [SigmaE2]); \end{verbatim} \end{small} @@ -576,7 +594,7 @@ This rule requires the induction formula to be a unary property of pairs,~$P(\pair{n,l})$. The alternative rule, {\tt ListN.mutual\_induct}, uses a binary property instead: -\[ \infer{\forall n\,l. \pair{n,l}\in\listn(A) \imp P(\pair{n,l})} +\[ \infer{\forall n\,l. \pair{n,l}\in\listn(A) \imp P(n,l)} {P(0,\Nil) & \infer*{P(\succ(n),\Cons(a,l))} {[a\in A & \pair{n,l}\in\listn(A) & P(n,l)]_{a,l,n}}} @@ -584,13 +602,14 @@ It is now a simple matter to prove theorems about $\listn(A)$, such as \[ \forall l\in\lst(A). \pair{\length(l),\, l}\in\listn(A) \] \[ \listn(A)``\{n\} = \{l\in\lst(A). \length(l)=n\} \] -This latter result --- here $r``A$ denotes the image of $A$ under $r$ +This latter result --- here $r``X$ denotes the image of $X$ under $r$ --- asserts that the inductive definition agrees with the obvious notion of $n$-element list. Unlike in Coq, the definition does not declare a new datatype. A `list of -$n$ elements' really is a list, and is subject to list operators such -as append. For example, a trivial induction yields +$n$ elements' really is a list and is subject to list operators such +as append (concatenation). For example, a trivial induction on +$\pair{m,l}\in\listn(A)$ yields \[ \infer{\pair{m\mathbin{+} m,\, l@l'}\in\listn(A)} {\pair{m,l}\in\listn(A) & \pair{m',l'}\in\listn(A)} \] @@ -598,7 +617,7 @@ \ifCADE\typeout{****Omitting mk_cases from CADE version!} \else -\subsection{A demonstration of {\tt mk\_cases}} +\subsection{A demonstration of {\tt mk\_cases}}\label{mkcases} The elimination rule, {\tt ListN.elim}, is cumbersome: \[ \infer{Q}{x\in\listn(A) & \infer*{Q}{[x = \pair{0,\Nil}]} & @@ -609,14 +628,15 @@ \pair{n,l}\in\listn(A) \end{array} \right]_{a,l,n}}} \] -The function {\tt ListN.mk\_cases} generates simplified instances of this -rule. It works by freeness reasoning on the list constructors. -If $x$ is $\pair{i,\Nil}$ or $\pair{i,\Cons(a,l)}$ then {\tt ListN.mk\_cases} -deduces the corresponding form of~$i$. For example, +The ML function {\tt ListN.mk\_cases} generates simplified instances of this +rule. It works by freeness reasoning on the list constructors: $\Cons$ is +injective and $\Cons(a,l)\not=\Nil$. If $x$ is $\pair{i,\Nil}$ or +$\pair{i,\Cons(a,l)}$ then {\tt ListN.mk\_cases} deduces the corresponding +form of~$i$. For example, \begin{ttbox} ListN.mk_cases List.con_defs "<i,Cons(a,l)> : listn(A)" \end{ttbox} -yields the rule +yields a rule with only two premises: \[ \infer{Q}{\pair{i, \Cons(a,l)}\in\listn(A) & \infer*{Q} {\left[\begin{array}{l} @@ -634,79 +654,78 @@ & \infer*{Q}{[a\in A &l\in\lst(A)]} } \] The most important uses of {\tt mk\_cases} concern inductive definitions of -evaluation relations. Then {\tt mk\_cases} supports the kind of backward -inference typical of hand proofs, for example to prove that the evaluation -relation is functional. +evaluation relations. Then {\tt mk\_cases} supports case analysis on +possible evaluations, for example to prove that evaluation is +functional. \fi %CADE -\subsection{A co-inductive definition: bisimulations on lazy lists} -This example anticipates the definition of the co-datatype $\llist(A)$, which -consists of lazy lists over~$A$. Its constructors are $\LNil$ and $\LCons$, -satisfying the introduction rules shown in~\S\ref{co-ind-sec}. +\subsection{A coinductive definition: bisimulations on lazy lists} +This example anticipates the definition of the codatatype $\llist(A)$, which +consists of finite and infinite lists over~$A$. Its constructors are $\LNil$ +and +$\LCons$, satisfying the introduction rules shown in~\S\ref{coind-sec}. Because $\llist(A)$ is defined as a greatest fixedpoint and uses the variant pairing and injection operators, it contains non-well-founded elements such as solutions to $\LCons(a,l)=l$. -The next step in the development of lazy lists is to define a co-induction +The next step in the development of lazy lists is to define a coinduction principle for proving equalities. This is done by showing that the equality relation on lazy lists is the greatest fixedpoint of some monotonic operation. The usual approach~\cite{pitts94} is to define some notion of bisimulation for lazy lists, define equivalence to be the greatest bisimulation, and finally to prove that two lazy lists are equivalent if and -only if they are equal. The co-induction rule for equivalence then yields a -co-induction principle for equalities. +only if they are equal. The coinduction rule for equivalence then yields a +coinduction principle for equalities. A binary relation $R$ on lazy lists is a {\bf bisimulation} provided $R\sbs R^+$, where $R^+$ is the relation -\[ \{\pair{\LNil;\LNil}\} \un - \{\pair{\LCons(a,l);\LCons(a,l')} . a\in A \conj \pair{l;l'}\in R\}. +\[ \{\pair{\LNil,\LNil}\} \un + \{\pair{\LCons(a,l),\LCons(a,l')} . a\in A \conj \pair{l,l'}\in R\}. \] -Variant pairs are used, $\pair{l;l'}$ instead of $\pair{l,l'}$, because this -is a co-inductive definition. A pair of lazy lists are {\bf equivalent} if they belong to some bisimulation. -Equivalence can be co-inductively defined as the greatest fixedpoint for the +Equivalence can be coinductively defined as the greatest fixedpoint for the introduction rules -\[ \pair{\LNil;\LNil} \in\lleq(A) \qquad - \infer[(-)]{\pair{\LCons(a,l);\LCons(a,l')} \in\lleq(A)} - {a\in A & \pair{l;l'}\in \lleq(A)} +\[ \pair{\LNil,\LNil} \in\lleq(A) \qquad + \infer[(-)]{\pair{\LCons(a,l),\LCons(a,l')} \in\lleq(A)} + {a\in A & \pair{l,l'}\in \lleq(A)} \] -To make this co-inductive definition, we invoke \verb|Co_Inductive_Fun|: +To make this coinductive definition, we invoke \verb|CoInductive_Fun|: \begin{ttbox} -structure LList_Eq = Co_Inductive_Fun +structure LList_Eq = CoInductive_Fun (val thy = LList.thy addconsts [(["lleq"],"i=>i")]; - val rec_doms = [("lleq", "llist(A) <*> llist(A)")]; + val rec_doms = [("lleq", "llist(A) * llist(A)")]; val sintrs = - ["<LNil; LNil> : lleq(A)", - "[| a:A; <l;l'>: lleq(A) |] ==> <LCons(a,l); LCons(a,l')>: lleq(A)"]; + ["<LNil, LNil> : lleq(A)", + "[| a:A; <l,l'>: lleq(A) |] ==> + <LCons(a,l), LCons(a,l')>: lleq(A)"]; val monos = []; val con_defs = []; - val type_intrs = LList.intrs@[QSigmaI]; - val type_elims = [QSigmaE2]); + val type_intrs = LList.intrs @ [SigmaI]; + val type_elims = [SigmaE2]); \end{ttbox} Again, {\tt addconsts} declares a constant for $\lleq$ in the parent theory. -The domain of $\lleq(A)$ is $\llist(A)\otimes\llist(A)$, where $\otimes$ -denotes the variant Cartesian product. The type-checking rules include the -introduction rules for lazy lists as well as rules expressinve both -definitions of the equivalence -\[ \pair{a;b}\in A\otimes B \bimp a\in A \conj b\in B. \] +The domain of $\lleq(A)$ is $\llist(A)\times\llist(A)$. The type-checking +rules include the introduction rules for lazy lists as well as rules +for both directions of the equivalence +$\pair{a,b}\in A\times B \bimp a\in A \conj b\in B$. The package returns the introduction rules and the elimination rule, as -usual. But instead of induction rules, it returns a co-induction rule. +usual. But instead of induction rules, it returns a coinduction rule. The rule is too big to display in the usual notation; its conclusion is -$a\in\lleq(A)$ and its premises are $a\in X$, $X\sbs \llist(A)\otimes\llist(A)$ -and -\[ \infer*{z=\pair{\LNil;\LNil}\disj \bigl(\exists a\,l\,l'.\, +$x\in\lleq(A)$ and its premises are $x\in X$, +${X\sbs\llist(A)\times\llist(A)}$ and +\[ \infer*{z=\pair{\LNil,\LNil}\disj \bigl(\exists a\,l\,l'.\, \begin{array}[t]{@{}l} - z=\pair{\LCons(a,l);\LCons(a,l')} \conj a\in A \conj{}\\ - \pair{l;l'}\in X\un\lleq(A) \bigr) + z=\pair{\LCons(a,l),\LCons(a,l')} \conj a\in A \conj{}\\ + \pair{l,l'}\in X\un\lleq(A) \bigr) \end{array} }{[z\in X]_z} \] -Thus if $a\in X$, where $X$ is a bisimulation contained in the -domain of $\lleq(A)$, then $a\in\lleq(A)$. It is easy to show that +Thus if $x\in X$, where $X$ is a bisimulation contained in the +domain of $\lleq(A)$, then $x\in\lleq(A)$. It is easy to show that $\lleq(A)$ is reflexive: the equality relation is a bisimulation. And $\lleq(A)$ is symmetric: its converse is a bisimulation. But showing that -$\lleq(A)$ coincides with the equality relation takes considerable work. +$\lleq(A)$ coincides with the equality relation takes some work. \subsection{The accessible part of a relation}\label{acc-sec} Let $\prec$ be a binary relation on~$D$; in short, $(\prec)\sbs D\times D$. @@ -716,13 +735,12 @@ inductively defined to be the least set that contains $a$ if it contains all $\prec$-predecessors of~$a$, for $a\in D$. Thus we need an introduction rule of the form -%%%%\[ \infer{a\in\acc(\prec)}{\infer*{y\in\acc(\prec)}{[y\prec a]_y}} \] \[ \infer{a\in\acc(\prec)}{\forall y.y\prec a\imp y\in\acc(\prec)} \] Paulin-Mohring treats this example in Coq~\cite{paulin92}, but it causes difficulties for other systems. Its premise does not conform to the structure of introduction rules for HOL's inductive definition package~\cite{camilleri92}. It is also unacceptable to Isabelle package -(\S\ref{intro-sec}), but fortunately can be transformed into one of the +(\S\ref{intro-sec}), but fortunately can be transformed into the acceptable form $t\in M(R)$. The powerset operator is monotonic, and $t\in\pow(R)$ is equivalent to @@ -732,15 +750,16 @@ the inverse image of~$\{a\}$ under~$\prec$. The ML invocation below follows this approach. Here $r$ is~$\prec$ and -$\field(r)$ refers to~$D$, the domain of $\acc(r)$. Finally $r^{-}``\{a\}$ -denotes the inverse image of~$\{a\}$ under~$r$. The package is supplied -the theorem {\tt Pow\_mono}, which asserts that $\pow$ is monotonic. +$\field(r)$ refers to~$D$, the domain of $\acc(r)$. (The field of a +relation is the union of its domain and range.) Finally +$r^{-}``\{a\}$ denotes the inverse image of~$\{a\}$ under~$r$. The package is +supplied the theorem {\tt Pow\_mono}, which asserts that $\pow$ is monotonic. \begin{ttbox} structure Acc = Inductive_Fun (val thy = WF.thy addconsts [(["acc"],"i=>i")]; val rec_doms = [("acc", "field(r)")]; val sintrs = - ["[| r-``\{a\} : Pow(acc(r)); a : field(r) |] ==> a : acc(r)"]; + ["[| r-``\{a\}: Pow(acc(r)); a: field(r) |] ==> a: acc(r)"]; val monos = [Pow_mono]; val con_defs = []; val type_intrs = []; @@ -766,7 +785,7 @@ introduction rules with arbitrary premises of the form $\forall \vec{y}.P(\vec{y})\imp f(\vec{y})\in R$. The premise can be expressed equivalently as -\[ \{z\in D. P(\vec{y}) \conj z=f(\vec{y})\} \] +\[ \{z\in D. P(\vec{y}) \conj z=f(\vec{y})\} \in \pow(R) \] provided $f(\vec{y})\in D$ for all $\vec{y}$ such that~$P(\vec{y})$. The following section demonstrates another use of the premise $t\in M(R)$, where $M=\lst$. @@ -811,22 +830,22 @@ each operation on primitive recursive functions combined just two functions. \begin{figure} -\begin{ttbox} +\begin{small}\begin{verbatim} structure Primrec = Inductive_Fun (val thy = Primrec0.thy; val rec_doms = [("primrec", "list(nat)->nat")]; - val ext = None + val ext = None; val sintrs = ["SC : primrec", "k: nat ==> CONST(k) : primrec", "i: nat ==> PROJ(i) : primrec", - "[| g: primrec; fs: list(primrec) |] ==> COMP(g,fs): primrec", - "[| f: primrec; g: primrec |] ==> PREC(f,g): primrec"]; + "[| g: primrec; fs: list(primrec) |] ==> COMP(g,fs): primrec", + "[| f: primrec; g: primrec |] ==> PREC(f,g): primrec"]; val monos = [list_mono]; val con_defs = [SC_def,CONST_def,PROJ_def,COMP_def,PREC_def]; - val type_intrs = pr0_typechecks + val type_intrs = pr0_typechecks; val type_elims = []); -\end{ttbox} +\end{verbatim}\end{small} \hrule \caption{Inductive definition of the primitive recursive functions} \label{primrec-fig} @@ -842,7 +861,7 @@ Due to the use of $\lst$ as a monotone operator, the composition case has an unusual induction hypothesis: \[ \infer*{P(\COMP(g,\fs))} - {[g\in\primrec & \fs\in\lst(\{z\in\primrec.P(x)\})]_{\fs,g}} \] + {[g\in\primrec & \fs\in\lst(\{z\in\primrec.P(z)\})]_{\fs,g}} \] The hypothesis states that $\fs$ is a list of primitive recursive functions satisfying the induction formula. Proving the $\COMP$ case typically requires structural induction on lists, yielding two subcases: either $\fs=\Nil$ or @@ -865,20 +884,20 @@ tradition. -\section{Datatypes and co-datatypes}\label{data-sec} -A (co-)datatype definition is a (co-)inductive definition with automatically -defined constructors and case analysis operator. The package proves that the +\section{Datatypes and codatatypes}\label{data-sec} +A (co)datatype definition is a (co)inductive definition with automatically +defined constructors and a case analysis operator. The package proves that the case operator inverts the constructors, and can also prove freeness theorems involving any pair of constructors. -\subsection{Constructors and their domain} -Conceptually, our two forms of definition are distinct: a (co-)inductive -definition selects a subset of an existing set, but a (co-)datatype +\subsection{Constructors and their domain}\label{univ-sec} +Conceptually, our two forms of definition are distinct: a (co)inductive +definition selects a subset of an existing set, but a (co)datatype definition creates a new set. But the package reduces the latter to the former. A set having strong closure properties must serve as the domain -of the (co-)inductive definition. Constructing this set requires some -theoretical effort. Consider first datatypes and then co-datatypes. +of the (co)inductive definition. Constructing this set requires some +theoretical effort. Consider first datatypes and then codatatypes. Isabelle/ZF defines the standard notion of Cartesian product $A\times B$, containing ordered pairs $\pair{a,b}$. Now the $m$-tuple @@ -890,7 +909,7 @@ A datatype constructor $\Con(x_1,\ldots\,x_m)$ is defined to be $h(\pair{x_1,\ldots\,x_m})$, where $h$ is composed of $\Inl$ and~$\Inr$. In a mutually recursive definition, all constructors for the set~$R_i$ have -the outer form~$h_{i,n}$, where $h_{i,n}$ is the injection described +the outer form~$h_{in}$, where $h_{in}$ is the injection described in~\S\ref{mutual-sec}. Further nested injections ensure that the constructors for~$R_i$ are pairwise distinct. @@ -903,30 +922,31 @@ The standard pairs and injections can only yield well-founded constructions. This eases the (manual!) definition of recursive functions -over datatypes. But they are unsuitable for co-datatypes, which typically +over datatypes. But they are unsuitable for codatatypes, which typically contain non-well-founded objects. -To support co-datatypes, Isabelle/ZF defines a variant notion of ordered +To support codatatypes, Isabelle/ZF defines a variant notion of ordered pair, written~$\pair{a;b}$. It also defines the corresponding variant notion of Cartesian product $A\otimes B$, variant injections $\QInl(a)$ and~$\QInr(b)$, and variant disjoint sum $A\oplus B$. Finally it defines the set $\quniv(A)$, which contains~$A$ and furthermore contains $\pair{a;b}$, $\QInl(a)$ and $\QInr(b)$ for $a$, $b\in\quniv(A)$. In a -typical co-datatype definition with set parameters $A_1$, \ldots, $A_k$, a -suitable domain is $\quniv(A_1\un\cdots\un A_k)$. This approach is an -alternative to adopting an Anti-Foundation -Axiom~\cite{aczel88}.\footnote{No reference is available. Variant pairs - are defined by $\pair{a;b}\equiv a+b \equiv (\{0\}\times a) \un (\{1\}\times - b)$, where $\times$ is the Cartesian product for standard ordered pairs. Now +typical codatatype definition with set parameters $A_1$, \ldots, $A_k$, a +suitable domain is $\quniv(A_1\un\cdots\un A_k)$. This approach using +standard ZF set theory\footnote{No reference is available. Variant pairs + are defined by $\pair{a;b}\equiv (a+b) \equiv (\{0\}\times a) \un + (\{1\}\times b)$, where $\times$ is the Cartesian product for standard + ordered pairs. Now $\pair{a;b}$ is injective and monotonic in its two arguments. Non-well-founded constructions, such as infinite lists, are constructed as least fixedpoints; the bounding set typically has the form $\univ(a_1\un\cdots\un a_k)$, where $a_1$, \ldots, $a_k$ are specified elements of the construction.} - +is an alternative to adopting Aczel's Anti-Foundation +Axiom~\cite{aczel88}. \subsection{The case analysis operator} -The (co-)datatype package automatically defines a case analysis operator, +The (co)datatype package automatically defines a case analysis operator, called {\tt$R$\_case}. A mutually recursive definition still has only one operator, called {\tt$R_1$\_\ldots\_$R_n$\_case}. The case operator is analogous to those for products and sums. @@ -945,9 +965,12 @@ R\hbox{\_case}(f_1,\ldots,f_k, {\tt Con}_i(\vec{x})) & = & f_i(\vec{x}), \qquad i = 1, \ldots, k \end{eqnarray*} -Note that if $f$ and $g$ have meta-type $i\To i$ then so do $\split(f)$ and -$\case(f,g)$. This works because $\split$ and $\case$ operate on their -last argument. They are easily combined to make complex case analysis +The case operator's definition takes advantage of Isabelle's representation +of syntax in the typed $\lambda$-calculus; it could readily be adapted to a +theorem prover for higher-order logic. If $f$ and~$g$ have meta-type +$i\To i$ then so do $\split(f)$ and +$\case(f,g)$. This works because $\split$ and $\case$ operate on their last +argument. They are easily combined to make complex case analysis operators. Here are two examples: \begin{itemize} \item $\split(\lambda x.\split(f(x)))$ performs case analysis for @@ -967,13 +990,13 @@ & = & g(b) \end{eqnarray*} \end{itemize} -Co-datatype definitions are treated in precisely the same way. They express +Codatatype definitions are treated in precisely the same way. They express case operators using those for the variant products and sums, namely $\qsplit$ and~$\qcase$. \ifCADE The package has processed all the datatypes discussed in my earlier -paper~\cite{paulson-set-II} and the co-datatype of lazy lists. Space +paper~\cite{paulson-set-II} and the codatatype of lazy lists. Space limitations preclude discussing these examples here, but they are distributed with Isabelle. \typeout{****Omitting datatype examples from CADE version!} \else @@ -991,12 +1014,12 @@ [(["Nil"], "i"), (["Cons"], "[i,i]=>i")])]; val rec_styp = "i=>i"; - val ext = None + val ext = None; val sintrs = ["Nil : list(A)", "[| a: A; l: list(A) |] ==> Cons(a,l) : list(A)"]; val monos = []; - val type_intrs = datatype_intrs + val type_intrs = datatype_intrs; val type_elims = datatype_elims); \end{ttbox} \hrule @@ -1004,29 +1027,29 @@ \medskip \begin{ttbox} -structure LList = Co_Datatype_Fun +structure LList = CoDatatype_Fun (val thy = QUniv.thy; val rec_specs = [("llist", "quniv(A)", [(["LNil"], "i"), (["LCons"], "[i,i]=>i")])]; val rec_styp = "i=>i"; - val ext = None + val ext = None; val sintrs = ["LNil : llist(A)", "[| a: A; l: llist(A) |] ==> LCons(a,l) : llist(A)"]; val monos = []; - val type_intrs = co_datatype_intrs - val type_elims = co_datatype_elims); + val type_intrs = codatatype_intrs; + val type_elims = codatatype_elims); \end{ttbox} \hrule -\caption{Defining the co-datatype of lazy lists} \label{llist-fig} +\caption{Defining the codatatype of lazy lists} \label{llist-fig} \end{figure} \subsection{Example: lists and lazy lists} Figures \ref{list-fig} and~\ref{llist-fig} present the ML definitions of lists and lazy lists, respectively. They highlight the (many) similarities -and (few) differences between datatype and co-datatype definitions. +and (few) differences between datatype and codatatype definitions. Each form of list has two constructors, one for the empty list and one for adding an element to a list. Each takes a parameter, defining the set of @@ -1039,7 +1062,8 @@ QUniv.thy}. \end{itemize} -Since $\lst(A)$ is a datatype, it enjoys a structural rule, {\tt List.induct}: +Since $\lst(A)$ is a datatype, it enjoys a structural induction rule, {\tt + List.induct}: \[ \infer{P(x)}{x\in\lst(A) & P(\Nil) & \infer*{P(\Cons(a,l))}{[a\in A & l\in\lst(A) & P(l)]_{a,l}} } \] @@ -1050,8 +1074,8 @@ is \[ \rank(l) < \rank(\Cons(a,l)). \] -Since $\llist(A)$ is a co-datatype, it has no induction rule. Instead it has -the co-induction rule shown in \S\ref{co-ind-sec}. Since variant pairs and +Since $\llist(A)$ is a codatatype, it has no induction rule. Instead it has +the coinduction rule shown in \S\ref{coind-sec}. Since variant pairs and injections are monotonic and need not have greater rank than their components, fixedpoint operators can create cyclic constructions. For example, the definition @@ -1077,11 +1101,11 @@ \lstcase(c, h, \Nil) & = & \case(\lambda u.c, \split(h), \Inl(\emptyset)) \\ & = & (\lambda u.c)(\emptyset) \\ - & = & c.\\[1ex] + & = & c\\[1ex] \lstcase(c, h, \Cons(x,y)) & = & \case(\lambda u.c, \split(h), \Inr(\pair{x,y})) \\ & = & \split(h, \pair{x,y}) \\ - & = & h(x,y). + & = & h(x,y) \end{eqnarray*} \begin{figure} @@ -1096,13 +1120,13 @@ [(["Fnil"], "i"), (["Fcons"], "[i,i]=>i")])]; val rec_styp = "i=>i"; - val ext = None + val ext = None; val sintrs = ["[| a:A; f: forest(A) |] ==> Tcons(a,f) : tree(A)", "Fnil : forest(A)", "[| t: tree(A); f: forest(A) |] ==> Fcons(t,f) : forest(A)"]; val monos = []; - val type_intrs = datatype_intrs + val type_intrs = datatype_intrs; val type_elims = datatype_elims); \end{verbatim} \end{small} @@ -1112,7 +1136,7 @@ \subsection{Example: mutual recursion} -In the mutually recursive trees/forests~\cite[\S4.5]{paulson-set-II}, trees +In mutually recursive trees and forests~\cite[\S4.5]{paulson-set-II}, trees have the one constructor $\Tcons$, while forests have the two constructors $\Fnil$ and~$\Fcons$. Figure~\ref{tf-fig} presents the ML definition. It has much in common with that of $\lst(A)$, including its @@ -1128,7 +1152,7 @@ \end{array} \right]_{a,f}} & P(\Fnil) - & \infer*{P(\Fcons(a,l))} + & \infer*{P(\Fcons(t,f))} {\left[\begin{array}{l} t\in\tree(A) \\ P(t) \\ f\in\forest(A) \\ P(f) \end{array} @@ -1150,7 +1174,7 @@ \end{array} \right]_{a,f}} & Q(\Fnil) - & \infer*{Q(\Fcons(a,l))} + & \infer*{Q(\Fcons(t,f))} {\left[\begin{array}{l} t\in\tree(A) \\ P(t) \\ f\in\forest(A) \\ Q(f) \end{array} @@ -1187,14 +1211,14 @@ (["Con2"], "[i,i]=>i"), (["Con3"], "[i,i,i]=>i")])]; val rec_styp = "[i,i]=>i"; - val ext = None + val ext = None; val sintrs = ["Con0 : data(A,B)", "[| a: A |] ==> Con1(a) : data(A,B)", "[| a: A; b: B |] ==> Con2(a,b) : data(A,B)", "[| a: A; b: B; d: data(A,B) |] ==> Con3(a,b,d) : data(A,B)"]; val monos = []; - val type_intrs = datatype_intrs + val type_intrs = datatype_intrs; val type_elims = datatype_elims); \end{verbatim} \end{small} @@ -1204,7 +1228,7 @@ \subsection{A four-constructor datatype} Finally let us consider a fairly general datatype. It has four -constructors $\Con_0$, $\Con_1$\ $\Con_2$ and $\Con_3$, with the +constructors $\Con_0$, \ldots, $\Con_3$, with the corresponding arities. Figure~\ref{data-fig} presents the ML definition. Because this datatype has two set parameters, $A$ and~$B$, it specifies $\univ(A\un B)$ as its domain. The structural induction rule has four @@ -1248,11 +1272,8 @@ quadratic in size. It is like the difference between the binary and unary numeral systems. -The package returns the constructor and case operator definitions as the -theorem list \verb|con_defs|. The head of this list defines the case -operator and the tail defines the constructors. - -The package returns the case equations, such as +The result structure contains the case operator and constructor definitions as +the theorem list \verb|con_defs|. It contains the case equations, such as \begin{eqnarray*} {\tt data\_case}(f_0,f_1,f_2,f_3,\Con_3(a,b,c)) & = & f_3(a,b,c), \end{eqnarray*} @@ -1280,7 +1301,7 @@ \Con_1(a)=c & \bimp & c=\Inl(\Inr(a)) \\ & \vdots & \\ \Inl(a)=\Inl(b) & \bimp & a=b \\ - \Inl(a)=\Inr(b) & \bimp & \bot \\ + \Inl(a)=\Inr(b) & \bimp & {\tt False} \\ \pair{a,b} = \pair{a',b'} & \bimp & a=a' \conj b=b' \end{eqnarray*} For example, these rewrite $\Con_1(a)=\Con_1(b)$ to $a=b$ in four steps. @@ -1298,8 +1319,8 @@ \fi %CADE \section{Conclusions and future work} -The fixedpoint approach makes it easy to implement a uniquely powerful -package for inductive and co-inductive definitions. It is efficient: it +The fixedpoint approach makes it easy to implement a powerful +package for inductive and coinductive definitions. It is efficient: it processes most definitions in seconds and even a 60-constructor datatype requires only two minutes. It is also simple: the package consists of under 1100 lines (35K bytes) of Standard ML code. The first working @@ -1310,11 +1331,11 @@ Indeed, Melham's inductive definition package for the HOL system~\cite{camilleri92} implicitly proves this theorem. -Datatype and co-datatype definitions furthermore require a particular set +Datatype and codatatype definitions furthermore require a particular set closed under a suitable notion of ordered pair. I intend to use the Isabelle/ZF package as the basis for a higher-order logic one, using Isabelle/HOL\@. The necessary theory is already -mechanizeds~\cite{paulson-coind}. HOL represents sets by unary predicates; +mechanized~\cite{paulson-coind}. HOL represents sets by unary predicates; defining the corresponding types may cause complication. @@ -1326,9 +1347,9 @@ \else \newpage \appendix -\section{Inductive and co-inductive definitions: users guide} -The ML functors \verb|Inductive_Fun| and \verb|Co_Inductive_Fun| build -inductive and co-inductive definitions, respectively. This section describes +\section{Inductive and coinductive definitions: users guide} +The ML functors \verb|Inductive_Fun| and \verb|CoInductive_Fun| build +inductive and coinductive definitions, respectively. This section describes how to invoke them. \subsection{The result structure} @@ -1356,8 +1377,11 @@ \end{description} For an inductive definition, the result structure contains two induction rules, -{\tt induct} and \verb|mutual_induct|. For a co-inductive definition, it -contains the rule \verb|co_induct|. +{\tt induct} and \verb|mutual_induct|. For a coinductive definition, it +contains the rule \verb|coinduct|. + +Figure~\ref{def-result-fig} summarizes the two result signatures, +specifying the types of all these components. \begin{figure} \begin{ttbox} @@ -1373,18 +1397,14 @@ {\it(Inductive definitions only)} val induct : thm val mutual_induct: thm -{\it(Co-inductive definitions only)} -val co_induct : thm +{\it(Coinductive definitions only)} +val coinduct : thm end \end{ttbox} \hrule -\caption{The result of a (co-)inductive definition} \label{def-result-fig} -\end{figure} +\caption{The result of a (co)inductive definition} \label{def-result-fig} -Figure~\ref{def-result-fig} summarizes the two result signatures, -specifying the types of all these components. - -\begin{figure} +\medskip \begin{ttbox} sig val thy : theory @@ -1397,11 +1417,11 @@ end \end{ttbox} \hrule -\caption{The argument of a (co-)inductive definition} \label{def-arg-fig} +\caption{The argument of a (co)inductive definition} \label{def-arg-fig} \end{figure} \subsection{The argument structure} -Both \verb|Inductive_Fun| and \verb|Co_Inductive_Fun| take the same argument +Both \verb|Inductive_Fun| and \verb|CoInductive_Fun| take the same argument structure (Figure~\ref{def-arg-fig}). Its components are as follows: \begin{description} \item[\tt thy] is the definition's parent theory, which {\it must\/} @@ -1416,9 +1436,9 @@ to a recursive set in the introduction rules. \item[\tt con\_defs] contains definitions of constants appearing in the -introduction rules. The (co-)datatype package supplies the constructors' +introduction rules. The (co)datatype package supplies the constructors' definitions here. Most direct calls of \verb|Inductive_Fun| or -\verb|Co_Inductive_Fun| pass the empty list; one exception is the primitive +\verb|CoInductive_Fun| pass the empty list; one exception is the primitive recursive functions example (\S\ref{primrec-sec}). \item[\tt type\_intrs] consists of introduction rules for type-checking the @@ -1448,14 +1468,14 @@ \end{itemize} -\section{Datatype and co-datatype definitions: users guide} -The ML functors \verb|Datatype_Fun| and \verb|Co_Datatype_Fun| define datatypes -and co-datatypes, invoking \verb|Datatype_Fun| and -\verb|Co_Datatype_Fun| to make the underlying (co-)inductive definitions. +\section{Datatype and codatatype definitions: users guide} +The ML functors \verb|Datatype_Fun| and \verb|CoDatatype_Fun| define datatypes +and codatatypes, invoking \verb|Datatype_Fun| and +\verb|CoDatatype_Fun| to make the underlying (co)inductive definitions. \subsection{The result structure} -The result structure extends that of (co-)inductive definitions +The result structure extends that of (co)inductive definitions (Figure~\ref{def-result-fig}) with several additional items: \begin{ttbox} val con_thy : theory @@ -1468,9 +1488,9 @@ Most of these have been discussed in~\S\ref{data-sec}. Here is a summary: \begin{description} \item[\tt con\_thy] is a new theory containing definitions of the -(co-)datatype's constructors and case operator. It also declares the +(co)datatype's constructors and case operator. It also declares the recursive sets as constants, so that it may serve as the parent -theory for the (co-)inductive definition. +theory for the (co)inductive definition. \item[\tt con\_defs] is a list of definitions: the case operator followed by the constructors. This theorem list can be supplied to \verb|mk_cases|, for @@ -1498,8 +1518,8 @@ \end{description} The result structure also inherits everything from the underlying -(co-)inductive definition, such as the introduction rules, elimination rule, -and induction/co-induction rule. +(co)inductive definition, such as the introduction rules, elimination rule, +and induction/coinduction rule. \begin{figure} @@ -1516,18 +1536,18 @@ end \end{ttbox} \hrule -\caption{The argument of a (co-)datatype definition} \label{data-arg-fig} +\caption{The argument of a (co)datatype definition} \label{data-arg-fig} \end{figure} \subsection{The argument structure} -Both (co-)datatype functors take the same argument structure -(Figure~\ref{data-arg-fig}). It does not extend that for (co-)inductive +Both (co)datatype functors take the same argument structure +(Figure~\ref{data-arg-fig}). It does not extend that for (co)inductive definitions, but shares several components and passes them uninterpreted to \verb|Datatype_Fun| or -\verb|Co_Datatype_Fun|. The new components are as follows: +\verb|CoDatatype_Fun|. The new components are as follows: \begin{description} -\item[\tt thy] is the (co-)datatype's parent theory. It {\it must not\/} -declare constants for the recursive sets. Recall that (co-)inductive +\item[\tt thy] is the (co)datatype's parent theory. It {\it must not\/} +declare constants for the recursive sets. Recall that (co)inductive definitions have the opposite restriction. \item[\tt rec\_specs] is a list of triples of the form ({\it recursive set\/}, @@ -1550,9 +1570,9 @@ products and disjoint sums \cite[\S4.2]{paulson-set-II}. In a typical datatype definition with set parameters $A_1$, \ldots, $A_k$, a suitable domain for all the recursive sets is $\univ(A_1\un\cdots\un A_k)$. For a -co-datatype definition, the set +codatatype definition, the set $\quniv(A)$ contains~$A$ and is closed under the variant Cartesian products -and disjoint sums; the appropropriate domain is +and disjoint sums; the appropriate domain is $\quniv(A_1\un\cdots\un A_k)$. The {\tt sintrs} specify the introduction rules, which govern the recursive @@ -1560,7 +1580,7 @@ and side-conditions to express things that go beyond the usual notion of datatype. The theorem lists {\tt monos}, {\tt type\_intrs} and {\tt type\_elims} should contain precisely what is needed for the underlying -(co-)inductive definition. Isabelle/ZF defines theorem lists that can be +(co)inductive definition. Isabelle/ZF defines theorem lists that can be defined for the latter two components: \begin{itemize} \item {\tt datatype\_intrs} and {\tt datatype\_elims} are type-checking rules