496 This section presents several examples: the finite powerset operator, |
497 This section presents several examples: the finite powerset operator, |
497 lists of $n$ elements, bisimulations on lazy lists, the well-founded part |
498 lists of $n$ elements, bisimulations on lazy lists, the well-founded part |
498 of a relation, and the primitive recursive functions. |
499 of a relation, and the primitive recursive functions. |
499 |
500 |
500 \subsection{The finite powerset operator} |
501 \subsection{The finite powerset operator} |
501 This operator has been discussed extensively above. Here |
502 This operator has been discussed extensively above. Here is the |
502 is the corresponding ML invocation (note that $\cons(a,b)$ abbreviates |
503 corresponding invocation in an Isabelle theory file. Note that |
503 $\{a\}\un b$ in Isabelle/ZF): |
504 $\cons(a,b)$ abbreviates $\{a\}\un b$ in Isabelle/ZF. |
504 \begin{ttbox} |
505 \begin{ttbox} |
505 structure Fin = Inductive_Fun |
506 Finite = Arith + |
506 (val thy = Arith.thy |> add_consts [("Fin", "i=>i", NoSyn)] |
507 consts Fin :: "i=>i" |
507 val thy_name = "Fin" |
508 inductive |
508 val rec_doms = [("Fin","Pow(A)")] |
509 domains "Fin(A)" <= "Pow(A)" |
509 val sintrs = ["0 : Fin(A)", |
510 intrs |
510 "[| a: A; b: Fin(A) |] ==> cons(a,b) : Fin(A)"] |
511 emptyI "0 : Fin(A)" |
511 val monos = [] |
512 consI "[| a: A; b: Fin(A) |] ==> cons(a,b) : Fin(A)" |
512 val con_defs = [] |
513 type_intrs "[empty_subsetI, cons_subsetI, PowI]" |
513 val type_intrs = [empty_subsetI, cons_subsetI, PowI] |
514 type_elims "[make_elim PowD]" |
514 val type_elims = [make_elim PowD]); |
515 end |
515 \end{ttbox} |
516 \end{ttbox} |
516 We apply the functor {\tt Inductive\_Fun} to a structure describing the |
517 Theory {\tt Finite} extends the parent theory {\tt Arith} by declaring the |
517 desired inductive definition. The parent theory~{\tt thy} is obtained from |
518 unary function symbol~$\Fin$, which is defined inductively. Its domain is |
518 {\tt Arith.thy} by adding the unary function symbol~$\Fin$. Its domain is |
|
519 specified as $\pow(A)$, where $A$ is the parameter appearing in the |
519 specified as $\pow(A)$, where $A$ is the parameter appearing in the |
520 introduction rules. For type-checking, the structure supplies introduction |
520 introduction rules. For type-checking, we supply two introduction |
521 rules: |
521 rules: |
522 \[ \emptyset\sbs A \qquad |
522 \[ \emptyset\sbs A \qquad |
523 \infer{\{a\}\un B\sbs C}{a\in C & B\sbs C} |
523 \infer{\{a\}\un B\sbs C}{a\in C & B\sbs C} |
524 \] |
524 \] |
525 A further introduction rule and an elimination rule express the two |
525 A further introduction rule and an elimination rule express the two |
526 directions of the equivalence $A\in\pow(B)\bimp A\sbs B$. Type-checking |
526 directions of the equivalence $A\in\pow(B)\bimp A\sbs B$. Type-checking |
527 involves mostly introduction rules. |
527 involves mostly introduction rules. |
528 |
528 |
529 ML is Isabelle's top level, so such functor invocations can take place at |
529 Like all Isabelle theory files, this one yields a structure containing the |
530 any time. The result structure is declared with the name~{\tt Fin}; we can |
530 new theory as an \ML{} value. Structure {\tt Finite} also has a |
531 refer to the $\Fin(A)$ introduction rules as {\tt Fin.intrs}, the induction |
531 substructure, called~{\tt Fin}. After declaring \hbox{\tt open Finite;} we |
532 rule as {\tt Fin.induct} and so forth. There are plans to integrate the |
532 can refer to the $\Fin(A)$ introduction rules as the list {\tt Fin.intrs} |
533 package better into Isabelle so that users can place inductive definitions |
533 or individually as {\tt Fin.emptyI} and {\tt Fin.consI}. The induction |
534 in Isabelle theory files instead of applying functors. |
534 rule is {\tt Fin.induct}. |
535 |
535 |
536 |
536 |
537 \subsection{Lists of $n$ elements}\label{listn-sec} |
537 \subsection{Lists of $n$ elements}\label{listn-sec} |
538 This has become a standard example of an inductive definition. Following |
538 This has become a standard example of an inductive definition. Following |
539 Paulin-Mohring~\cite{paulin92}, we could attempt to define a new datatype |
539 Paulin-Mohring~\cite{paulin92}, we could attempt to define a new datatype |
543 \infer{\hbox{\tt Consn}(n,a,l)\in\listn(A,\succ(n))} |
543 \infer{\hbox{\tt Consn}(n,a,l)\in\listn(A,\succ(n))} |
544 {n\in\nat & a\in A & l\in\listn(A,n)} |
544 {n\in\nat & a\in A & l\in\listn(A,n)} |
545 \] |
545 \] |
546 are not acceptable to the inductive definition package: |
546 are not acceptable to the inductive definition package: |
547 $\listn$ occurs with three different parameter lists in the definition. |
547 $\listn$ occurs with three different parameter lists in the definition. |
548 |
|
549 \begin{figure} |
|
550 \begin{ttbox} |
|
551 structure ListN = Inductive_Fun |
|
552 (val thy = ListFn.thy |> add_consts [("listn","i=>i",NoSyn)] |
|
553 val thy_name = "ListN" |
|
554 val rec_doms = [("listn", "nat*list(A)")] |
|
555 val sintrs = |
|
556 ["<0,Nil>: listn(A)", |
|
557 "[| a: A; <n,l>: listn(A) |] ==> <succ(n), Cons(a,l)>: listn(A)"] |
|
558 val monos = [] |
|
559 val con_defs = [] |
|
560 val type_intrs = nat_typechecks @ List.intrs @ [SigmaI] |
|
561 val type_elims = []); |
|
562 \end{ttbox} |
|
563 \hrule |
|
564 \caption{Defining lists of $n$ elements} \label{listn-fig} |
|
565 \end{figure} |
|
566 |
548 |
567 The Isabelle/ZF version of this example suggests a general treatment of |
549 The Isabelle/ZF version of this example suggests a general treatment of |
568 varying parameters. Here, we use the existing datatype definition of |
550 varying parameters. Here, we use the existing datatype definition of |
569 $\lst(A)$, with constructors $\Nil$ and~$\Cons$. Then incorporate the |
551 $\lst(A)$, with constructors $\Nil$ and~$\Cons$. Then incorporate the |
570 parameter~$n$ into the inductive set itself, defining $\listn(A)$ as a |
552 parameter~$n$ into the inductive set itself, defining $\listn(A)$ as a |
574 rules are |
556 rules are |
575 \[ \pair{0,\Nil}\in\listn(A) \qquad |
557 \[ \pair{0,\Nil}\in\listn(A) \qquad |
576 \infer{\pair{\succ(n),\Cons(a,l)}\in\listn(A)} |
558 \infer{\pair{\succ(n),\Cons(a,l)}\in\listn(A)} |
577 {a\in A & \pair{n,l}\in\listn(A)} |
559 {a\in A & \pair{n,l}\in\listn(A)} |
578 \] |
560 \] |
579 Figure~\ref{listn-fig} presents the ML invocation. A theory of lists, |
561 The Isabelle theory file takes, as parent, the theory~{\tt List} of lists. |
580 extended with a declaration of $\listn$, is the parent theory. The domain |
562 We declare the constant~$\listn$ and supply an inductive definition, |
581 is specified as $\nat\times\lst(A)$. The type-checking rules include those |
563 specifying the domain as $\nat\times\lst(A)$: |
582 for 0, $\succ$, $\Nil$ and $\Cons$. Because $\listn(A)$ is a set of pairs, |
564 \begin{ttbox} |
583 type-checking also requires introduction and elimination rules to express |
565 ListN = List + |
584 both directions of the equivalence $\pair{a,b}\in A\times B \bimp a\in A |
566 consts listn ::"i=>i" |
585 \conj b\in B$. |
567 inductive |
|
568 domains "listn(A)" <= "nat*list(A)" |
|
569 intrs |
|
570 NilI "<0,Nil> : listn(A)" |
|
571 ConsI "[| a: A; <n,l> : listn(A) |] ==> <succ(n), Cons(a,l)> : listn(A)" |
|
572 type_intrs "nat_typechecks @ list.intrs" |
|
573 end |
|
574 \end{ttbox} |
|
575 The type-checking rules include those for 0, $\succ$, $\Nil$ and $\Cons$. |
|
576 Because $\listn(A)$ is a set of pairs, type-checking requires the |
|
577 equivalence $\pair{a,b}\in A\times B \bimp a\in A \conj b\in B$; the |
|
578 package always includes the necessary rules. |
586 |
579 |
587 The package returns introduction, elimination and induction rules for |
580 The package returns introduction, elimination and induction rules for |
588 $\listn$. The basic induction rule, {\tt ListN.induct}, is |
581 $\listn$. The basic induction rule, {\tt ListN.induct}, is |
589 \[ \infer{P(x)}{x\in\listn(A) & P(\pair{0,\Nil}) & |
582 \[ \infer{P(x)}{x\in\listn(A) & P(\pair{0,\Nil}) & |
590 \infer*{P(\pair{\succ(n),\Cons(a,l)})} |
583 \infer*{P(\pair{\succ(n),\Cons(a,l)})} |
685 introduction rules |
678 introduction rules |
686 \[ \pair{\LNil,\LNil} \in\lleq(A) \qquad |
679 \[ \pair{\LNil,\LNil} \in\lleq(A) \qquad |
687 \infer[(-)]{\pair{\LCons(a,l),\LCons(a,l')} \in\lleq(A)} |
680 \infer[(-)]{\pair{\LCons(a,l),\LCons(a,l')} \in\lleq(A)} |
688 {a\in A & \pair{l,l'}\in \lleq(A)} |
681 {a\in A & \pair{l,l'}\in \lleq(A)} |
689 \] |
682 \] |
690 To make this coinductive definition, we invoke \verb|CoInductive_Fun|: |
683 To make this coinductive definition, the theory file includes (after the |
|
684 declaration of $\llist(A)$) the following lines: |
691 \begin{ttbox} |
685 \begin{ttbox} |
692 structure LList_Eq = CoInductive_Fun |
686 consts lleq :: "i=>i" |
693 (val thy = LList.thy |> add_consts [("lleq","i=>i",NoSyn)] |
687 coinductive |
694 val thy_name = "LList_Eq" |
688 domains "lleq(A)" <= "llist(A) * llist(A)" |
695 val rec_doms = [("lleq", "llist(A) * llist(A)")] |
689 intrs |
696 val sintrs = |
690 LNil "<LNil, LNil> : lleq(A)" |
697 ["<LNil, LNil> : lleq(A)", |
691 LCons "[| a:A; <l,l'>: lleq(A) |] ==> <LCons(a,l), LCons(a,l')>: lleq(A)" |
698 "[| a:A; <l,l'>: lleq(A) |] ==> <LCons(a,l),LCons(a,l')>: lleq(A)"] |
692 type_intrs "llist.intrs" |
699 val monos = [] |
|
700 val con_defs = [] |
|
701 val type_intrs = LList.intrs |
|
702 val type_elims = []); |
|
703 \end{ttbox} |
693 \end{ttbox} |
704 Again, {\tt addconsts} declares a constant for $\lleq$ in the parent theory. |
694 Again, {\tt addconsts} declares a constant for $\lleq$ in the parent theory. |
705 The domain of $\lleq(A)$ is $\llist(A)\times\llist(A)$. The type-checking |
695 The domain of $\lleq(A)$ is $\llist(A)\times\llist(A)$. The type-checking |
706 rules include the introduction rules for lazy lists as well as rules |
696 rules include the introduction rules for $\llist(A)$, whose |
707 for both directions of the equivalence |
697 declaration is discussed below (\S\ref{lists-sec}). |
708 $\pair{a,b}\in A\times B \bimp a\in A \conj b\in B$. |
|
709 |
698 |
710 The package returns the introduction rules and the elimination rule, as |
699 The package returns the introduction rules and the elimination rule, as |
711 usual. But instead of induction rules, it returns a coinduction rule. |
700 usual. But instead of induction rules, it returns a coinduction rule. |
712 The rule is too big to display in the usual notation; its conclusion is |
701 The rule is too big to display in the usual notation; its conclusion is |
713 $x\in\lleq(A)$ and its premises are $x\in X$, |
702 $x\in\lleq(A)$ and its premises are $x\in X$, |
747 $t\sbs R$. This in turn is equivalent to $\forall y\in t. y\in R$. To |
736 $t\sbs R$. This in turn is equivalent to $\forall y\in t. y\in R$. To |
748 express $\forall y.y\prec a\imp y\in\acc(\prec)$ we need only find a |
737 express $\forall y.y\prec a\imp y\in\acc(\prec)$ we need only find a |
749 term~$t$ such that $y\in t$ if and only if $y\prec a$. A suitable $t$ is |
738 term~$t$ such that $y\in t$ if and only if $y\prec a$. A suitable $t$ is |
750 the inverse image of~$\{a\}$ under~$\prec$. |
739 the inverse image of~$\{a\}$ under~$\prec$. |
751 |
740 |
752 The ML invocation below follows this approach. Here $r$ is~$\prec$ and |
741 The theory file below follows this approach. Here $r$ is~$\prec$ and |
753 $\field(r)$ refers to~$D$, the domain of $\acc(r)$. (The field of a |
742 $\field(r)$ refers to~$D$, the domain of $\acc(r)$. (The field of a |
754 relation is the union of its domain and range.) Finally |
743 relation is the union of its domain and range.) Finally $r^{-}``\{a\}$ |
755 $r^{-}``\{a\}$ denotes the inverse image of~$\{a\}$ under~$r$. The package is |
744 denotes the inverse image of~$\{a\}$ under~$r$. We supply the theorem {\tt |
756 supplied the theorem {\tt Pow\_mono}, which asserts that $\pow$ is monotonic. |
745 Pow\_mono}, which asserts that $\pow$ is monotonic. |
757 \begin{ttbox} |
746 \begin{ttbox} |
758 structure Acc = Inductive_Fun |
747 Acc = WF + |
759 (val thy = WF.thy |> add_consts [("acc","i=>i",NoSyn)] |
748 consts acc :: "i=>i" |
760 val thy_name = "Acc" |
749 inductive |
761 val rec_doms = [("acc", "field(r)")] |
750 domains "acc(r)" <= "field(r)" |
762 val sintrs = ["[| r-``\{a\}:\,Pow(acc(r)); a:\,field(r) |] ==> a:\,acc(r)"] |
751 intrs |
763 val monos = [Pow_mono] |
752 vimage "[| r-``\{a\}: Pow(acc(r)); a: field(r) |] ==> a: acc(r)" |
764 val con_defs = [] |
753 monos "[Pow_mono]" |
765 val type_intrs = [] |
754 end |
766 val type_elims = []); |
|
767 \end{ttbox} |
755 \end{ttbox} |
768 The Isabelle theory proceeds to prove facts about $\acc(\prec)$. For |
756 The Isabelle theory proceeds to prove facts about $\acc(\prec)$. For |
769 instance, $\prec$ is well-founded if and only if its field is contained in |
757 instance, $\prec$ is well-founded if and only if its field is contained in |
770 $\acc(\prec)$. |
758 $\acc(\prec)$. |
771 |
759 |
829 tuple-valued functions. This modified the inductive definition such that |
817 tuple-valued functions. This modified the inductive definition such that |
830 each operation on primitive recursive functions combined just two functions. |
818 each operation on primitive recursive functions combined just two functions. |
831 |
819 |
832 \begin{figure} |
820 \begin{figure} |
833 \begin{ttbox} |
821 \begin{ttbox} |
834 structure Primrec = Inductive_Fun |
822 Primrec = List + |
835 (val thy = Primrec0.thy |
823 consts |
836 val thy_name = "Primrec" |
824 primrec :: "i" |
837 val rec_doms = [("primrec", "list(nat)->nat")] |
825 SC :: "i" |
838 val sintrs = |
826 \(\vdots\) |
839 ["SC : primrec", |
827 defs |
840 "k: nat ==> CONST(k) : primrec", |
828 SC_def "SC == lam l:list(nat).list_case(0, %x xs.succ(x), l)" |
841 "i: nat ==> PROJ(i) : primrec", |
829 \(\vdots\) |
842 "[| g: primrec; fs: list(primrec) |] ==> COMP(g,fs): primrec", |
830 inductive |
843 "[| f: primrec; g: primrec |] ==> PREC(f,g): primrec"] |
831 domains "primrec" <= "list(nat)->nat" |
844 val monos = [list_mono] |
832 intrs |
845 val con_defs = [SC_def,CONST_def,PROJ_def,COMP_def,PREC_def] |
833 SC "SC : primrec" |
846 val type_intrs = pr0_typechecks |
834 CONST "k: nat ==> CONST(k) : primrec" |
847 val type_elims = []); |
835 PROJ "i: nat ==> PROJ(i) : primrec" |
|
836 COMP "[| g: primrec; fs: list(primrec) |] ==> COMP(g,fs): primrec" |
|
837 PREC "[| f: primrec; g: primrec |] ==> PREC(f,g): primrec" |
|
838 monos "[list_mono]" |
|
839 con_defs "[SC_def,CONST_def,PROJ_def,COMP_def,PREC_def]" |
|
840 type_intrs "nat_typechecks @ list.intrs @ \ttback |
|
841 \ttback [lam_type, list_case_type, drop_type, map_type, \ttback |
|
842 \ttback apply_type, rec_type]" |
|
843 end |
848 \end{ttbox} |
844 \end{ttbox} |
849 \hrule |
845 \hrule |
850 \caption{Inductive definition of the primitive recursive functions} |
846 \caption{Inductive definition of the primitive recursive functions} |
851 \label{primrec-fig} |
847 \label{primrec-fig} |
852 \end{figure} |
848 \end{figure} |
867 satisfying the induction formula. Proving the $\COMP$ case typically requires |
863 satisfying the induction formula. Proving the $\COMP$ case typically requires |
868 structural induction on lists, yielding two subcases: either $\fs=\Nil$ or |
864 structural induction on lists, yielding two subcases: either $\fs=\Nil$ or |
869 else $\fs=\Cons(f,\fs')$, where $f\in\primrec$, $P(f)$, and $\fs'$ is |
865 else $\fs=\Cons(f,\fs')$, where $f\in\primrec$, $P(f)$, and $\fs'$ is |
870 another list of primitive recursive functions satisfying~$P$. |
866 another list of primitive recursive functions satisfying~$P$. |
871 |
867 |
872 Figure~\ref{primrec-fig} presents the ML invocation. Theory {\tt |
868 Figure~\ref{primrec-fig} presents the theory file. Theory {\tt Primrec} |
873 Primrec0.thy} defines the constants $\SC$, $\CONST$, etc. These are not |
869 defines the constants $\SC$, $\CONST$, etc. These are not constructors of |
874 constructors of a new datatype, but functions over lists of numbers. Their |
870 a new datatype, but functions over lists of numbers. Their definitions, |
875 definitions, which are omitted, consist of routine list programming. In |
871 most of which are omitted, consist of routine list programming. In |
876 Isabelle/ZF, the primitive recursive functions are defined as a subset of |
872 Isabelle/ZF, the primitive recursive functions are defined as a subset of |
877 the function set $\lst(\nat)\to\nat$. |
873 the function set $\lst(\nat)\to\nat$. |
878 |
874 |
879 The Isabelle theory goes on to formalize Ackermann's function and prove |
875 The Isabelle theory goes on to formalize Ackermann's function and prove |
880 that it is not primitive recursive, using the induction rule {\tt |
876 that it is not primitive recursive, using the induction rule {\tt |
994 |
990 |
995 To see how constructors and the case analysis operator are defined, let us |
991 To see how constructors and the case analysis operator are defined, let us |
996 examine some examples. These include lists and trees/forests, which I have |
992 examine some examples. These include lists and trees/forests, which I have |
997 discussed extensively in another paper~\cite{paulson-set-II}. |
993 discussed extensively in another paper~\cite{paulson-set-II}. |
998 |
994 |
999 \begin{figure} |
995 |
|
996 \subsection{Example: lists and lazy lists}\label{lists-sec} |
|
997 Here is a theory file that declares the datatype of lists: |
1000 \begin{ttbox} |
998 \begin{ttbox} |
1001 structure List = Datatype_Fun |
999 List = Univ + |
1002 (val thy = Univ.thy |
1000 consts list :: "i=>i" |
1003 val thy_name = "List" |
1001 datatype "list(A)" = Nil | Cons ("a:A", "l: list(A)") |
1004 val rec_specs = [("list", "univ(A)", |
1002 end |
1005 [(["Nil"], "i", NoSyn), |
|
1006 (["Cons"], "[i,i]=>i", NoSyn)])] |
|
1007 val rec_styp = "i=>i" |
|
1008 val sintrs = ["Nil : list(A)", |
|
1009 "[| a: A; l: list(A) |] ==> Cons(a,l) : list(A)"] |
|
1010 val monos = [] |
|
1011 val type_intrs = datatype_intrs |
|
1012 val type_elims = datatype_elims); |
|
1013 \end{ttbox} |
1003 \end{ttbox} |
1014 \hrule |
1004 And here is the theory file that declares the codatatype of lazy lists: |
1015 \caption{Defining the datatype of lists} \label{list-fig} |
|
1016 |
|
1017 \medskip |
|
1018 \begin{ttbox} |
1005 \begin{ttbox} |
1019 structure LList = CoDatatype_Fun |
1006 LList = QUniv + |
1020 (val thy = QUniv.thy |
1007 consts llist :: "i=>i" |
1021 val thy_name = "LList" |
1008 codatatype "llist(A)" = LNil | LCons ("a: A", "l: llist(A)") |
1022 val rec_specs = [("llist", "quniv(A)", |
1009 end |
1023 [(["LNil"], "i", NoSyn), |
|
1024 (["LCons"], "[i,i]=>i", NoSyn)])] |
|
1025 val rec_styp = "i=>i" |
|
1026 val sintrs = ["LNil : llist(A)", |
|
1027 "[| a: A; l: llist(A) |] ==> LCons(a,l) : llist(A)"] |
|
1028 val monos = [] |
|
1029 val type_intrs = codatatype_intrs |
|
1030 val type_elims = codatatype_elims); |
|
1031 \end{ttbox} |
1010 \end{ttbox} |
1032 \hrule |
1011 They highlight the (many) similarities and (few) differences between |
1033 \caption{Defining the codatatype of lazy lists} \label{llist-fig} |
1012 datatype and codatatype definitions.\footnote{The real theory files contain |
1034 \end{figure} |
1013 many more declarations, mainly of functions over lists; the declaration |
1035 |
1014 of lazy lists is followed by the coinductive definition of lazy list |
1036 \subsection{Example: lists and lazy lists} |
1015 equality.} |
1037 Figures \ref{list-fig} and~\ref{llist-fig} present the ML definitions of |
|
1038 lists and lazy lists, respectively. They highlight the (many) similarities |
|
1039 and (few) differences between datatype and codatatype definitions. |
|
1040 |
1016 |
1041 Each form of list has two constructors, one for the empty list and one for |
1017 Each form of list has two constructors, one for the empty list and one for |
1042 adding an element to a list. Each takes a parameter, defining the set of |
1018 adding an element to a list. Each takes a parameter, defining the set of |
1043 lists over a given set~$A$. Each uses the appropriate domain from a |
1019 lists over a given set~$A$. Each uses the appropriate domain from a |
1044 Isabelle/ZF theory: |
1020 Isabelle/ZF theory: |
1045 \begin{itemize} |
1021 \begin{itemize} |
1046 \item $\lst(A)$ specifies domain $\univ(A)$ and parent theory {\tt Univ.thy}. |
1022 \item $\lst(A)$ requires the parent theory {\tt Univ}. The package |
1047 |
1023 automatically uses the domain $\univ(A)$ (the default choice can be |
1048 \item $\llist(A)$ specifies domain $\quniv(A)$ and parent theory {\tt |
1024 overridden). |
1049 QUniv.thy}. |
1025 |
|
1026 \item $\llist(A)$ requires the parent theory {\tt QUniv}. The package |
|
1027 automatically uses the domain $\quniv(A)$. |
1050 \end{itemize} |
1028 \end{itemize} |
1051 |
1029 |
1052 Since $\lst(A)$ is a datatype, it enjoys a structural induction rule, {\tt |
1030 Since $\lst(A)$ is a datatype, it enjoys a structural induction rule, {\tt |
1053 List.induct}: |
1031 List.induct}: |
1054 \[ \infer{P(x)}{x\in\lst(A) & P(\Nil) |
1032 \[ \infer{P(x)}{x\in\lst(A) & P(\Nil) |
1093 \case(\lambda u.c, \split(h), \Inr(\pair{x,y})) \\ |
1071 \case(\lambda u.c, \split(h), \Inr(\pair{x,y})) \\ |
1094 & = & \split(h, \pair{x,y}) \\ |
1072 & = & \split(h, \pair{x,y}) \\ |
1095 & = & h(x,y) |
1073 & = & h(x,y) |
1096 \end{eqnarray*} |
1074 \end{eqnarray*} |
1097 |
1075 |
1098 \begin{figure} |
|
1099 \begin{ttbox} |
|
1100 structure TF = Datatype_Fun |
|
1101 (val thy = Univ.thy |
|
1102 val thy_name = "TF" |
|
1103 val rec_specs = [("tree", "univ(A)", |
|
1104 [(["Tcons"], "[i,i]=>i", NoSyn)]), |
|
1105 ("forest", "univ(A)", |
|
1106 [(["Fnil"], "i", NoSyn), |
|
1107 (["Fcons"], "[i,i]=>i", NoSyn)])] |
|
1108 val rec_styp = "i=>i" |
|
1109 val sintrs = |
|
1110 ["[| a:A; f: forest(A) |] ==> Tcons(a,f) : tree(A)", |
|
1111 "Fnil : forest(A)", |
|
1112 "[| t: tree(A); f: forest(A) |] ==> Fcons(t,f) : forest(A)"] |
|
1113 val monos = [] |
|
1114 val type_intrs = datatype_intrs |
|
1115 val type_elims = datatype_elims); |
|
1116 \end{ttbox} |
|
1117 \hrule |
|
1118 \caption{Defining the datatype of trees and forests} \label{tf-fig} |
|
1119 \end{figure} |
|
1120 |
|
1121 |
1076 |
1122 \subsection{Example: mutual recursion} |
1077 \subsection{Example: mutual recursion} |
1123 In mutually recursive trees and forests~\cite[\S4.5]{paulson-set-II}, trees |
1078 In mutually recursive trees and forests~\cite[\S4.5]{paulson-set-II}, trees |
1124 have the one constructor $\Tcons$, while forests have the two constructors |
1079 have the one constructor $\Tcons$, while forests have the two constructors |
1125 $\Fnil$ and~$\Fcons$. Figure~\ref{tf-fig} presents the ML |
1080 $\Fnil$ and~$\Fcons$: |
1126 definition. It has much in common with that of $\lst(A)$, including its |
1081 \begin{ttbox} |
1127 use of $\univ(A)$ for the domain and {\tt Univ.thy} for the parent theory. |
1082 TF = List + |
|
1083 consts tree, forest, tree_forest :: "i=>i" |
|
1084 datatype "tree(A)" = Tcons ("a: A", "f: forest(A)") |
|
1085 and "forest(A)" = Fnil | Fcons ("t: tree(A)", "f: forest(A)") |
|
1086 end |
|
1087 \end{ttbox} |
1128 The three introduction rules define the mutual recursion. The |
1088 The three introduction rules define the mutual recursion. The |
1129 distinguishing feature of this example is its two induction rules. |
1089 distinguishing feature of this example is its two induction rules. |
1130 |
1090 |
1131 The basic induction rule is called {\tt TF.induct}: |
1091 The basic induction rule is called {\tt TF.induct}: |
1132 \[ \infer{P(x)}{x\in\TF(A) & |
1092 \[ \infer{P(x)}{x\in\TF(A) & |
1181 \begin{eqnarray*} |
1141 \begin{eqnarray*} |
1182 {\tt tree\_forest\_case}(f,c,g) & \equiv & |
1142 {\tt tree\_forest\_case}(f,c,g) & \equiv & |
1183 \case(\split(f),\, \case(\lambda u.c, \split(g))) |
1143 \case(\split(f),\, \case(\lambda u.c, \split(g))) |
1184 \end{eqnarray*} |
1144 \end{eqnarray*} |
1185 |
1145 |
1186 \begin{figure} |
|
1187 \begin{ttbox} |
|
1188 structure Data = Datatype_Fun |
|
1189 (val thy = Univ.thy |
|
1190 val thy_name = "Data" |
|
1191 val rec_specs = [("data", "univ(A Un B)", |
|
1192 [(["Con0"], "i", NoSyn), |
|
1193 (["Con1"], "i=>i", NoSyn), |
|
1194 (["Con2"], "[i,i]=>i", NoSyn), |
|
1195 (["Con3"], "[i,i,i]=>i", NoSyn)])] |
|
1196 val rec_styp = "[i,i]=>i" |
|
1197 val sintrs = |
|
1198 ["Con0 : data(A,B)", |
|
1199 "[| a: A |] ==> Con1(a) : data(A,B)", |
|
1200 "[| a: A; b: B |] ==> Con2(a,b) : data(A,B)", |
|
1201 "[| a: A; b: B; d: data(A,B) |] ==> Con3(a,b,d) : data(A,B)"] |
|
1202 val monos = [] |
|
1203 val type_intrs = datatype_intrs |
|
1204 val type_elims = datatype_elims); |
|
1205 \end{ttbox} |
|
1206 \hrule |
|
1207 \caption{Defining the four-constructor sample datatype} \label{data-fig} |
|
1208 \end{figure} |
|
1209 |
1146 |
1210 \subsection{A four-constructor datatype} |
1147 \subsection{A four-constructor datatype} |
1211 Finally let us consider a fairly general datatype. It has four |
1148 Finally let us consider a fairly general datatype. It has four |
1212 constructors $\Con_0$, \ldots, $\Con_3$, with the |
1149 constructors $\Con_0$, \ldots, $\Con_3$, with the corresponding arities. |
1213 corresponding arities. Figure~\ref{data-fig} presents the ML definition. |
1150 \begin{ttbox} |
1214 Because this datatype has two set parameters, $A$ and~$B$, it specifies |
1151 Data = Univ + |
1215 $\univ(A\un B)$ as its domain. The structural induction rule has four |
1152 consts data :: "[i,i] => i" |
1216 minor premises, one per constructor: |
1153 datatype "data(A,B)" = Con0 |
|
1154 | Con1 ("a: A") |
|
1155 | Con2 ("a: A", "b: B") |
|
1156 | Con3 ("a: A", "b: B", "d: data(A,B)") |
|
1157 end |
|
1158 \end{ttbox} |
|
1159 Because this datatype has two set parameters, $A$ and~$B$, the package |
|
1160 automatically supplies $\univ(A\un B)$ as its domain. The structural |
|
1161 induction rule has four minor premises, one per constructor: |
1217 \[ \infer{P(x)}{x\in\data(A,B) & |
1162 \[ \infer{P(x)}{x\in\data(A,B) & |
1218 P(\Con_0) & |
1163 P(\Con_0) & |
1219 \infer*{P(\Con_1(a))}{[a\in A]_a} & |
1164 \infer*{P(\Con_1(a))}{[a\in A]_a} & |
1220 \infer*{P(\Con_2(a,b))} |
1165 \infer*{P(\Con_2(a,b))} |
1221 {\left[\begin{array}{l} a\in A \\ b\in B \end{array} |
1166 {\left[\begin{array}{l} a\in A \\ b\in B \end{array} |
1445 val coinduct : thm |
1396 val coinduct : thm |
1446 end |
1397 end |
1447 \end{ttbox} |
1398 \end{ttbox} |
1448 \hrule |
1399 \hrule |
1449 \caption{The result of a (co)inductive definition} \label{def-result-fig} |
1400 \caption{The result of a (co)inductive definition} \label{def-result-fig} |
1450 |
1401 \end{figure} |
1451 \medskip |
1402 |
|
1403 \subsection{The syntax of a (co)inductive definition} |
|
1404 An inductive definition has the form |
1452 \begin{ttbox} |
1405 \begin{ttbox} |
1453 sig |
1406 inductive |
1454 val thy : theory |
1407 domains {\it domain declarations} |
1455 val thy_name : string |
1408 intrs {\it introduction rules} |
1456 val rec_doms : (string*string) list |
1409 monos {\it monotonicity theorems} |
1457 val sintrs : string list |
1410 con_defs {\it constructor definitions} |
1458 val monos : thm list |
1411 type_intrs {\it introduction rules for type-checking} |
1459 val con_defs : thm list |
1412 type_elims {\it elimination rules for type-checking} |
1460 val type_intrs : thm list |
|
1461 val type_elims : thm list |
|
1462 end |
|
1463 \end{ttbox} |
1413 \end{ttbox} |
1464 \hrule |
1414 A coinductive definition is identical save that it starts with the keyword |
1465 \caption{The argument of a (co)inductive definition} \label{def-arg-fig} |
1415 {\tt coinductive}. |
1466 \end{figure} |
1416 |
1467 |
1417 The {\tt monos}, {\tt con\_defs}, {\tt type\_intrs} and {\tt type\_elims} |
1468 \subsection{The argument structure} |
1418 sections are optional. If present, each is specified as a string, which |
1469 Both \verb|Inductive_Fun| and \verb|CoInductive_Fun| take the same argument |
1419 must be a valid ML expression of type {\tt thm list}. It is simply |
1470 structure (Figure~\ref{def-arg-fig}). Its components are as follows: |
1420 inserted into the {\tt .thy.ML} file; if it is ill-formed, it will trigger |
|
1421 ML error messages. You can then inspect the file on your directory. |
|
1422 |
1471 \begin{description} |
1423 \begin{description} |
1472 \item[\tt thy] is the definition's parent theory, which {\it must\/} |
1424 \item[\it domain declarations] consist of one or more items of the form |
1473 declare constants for the recursive sets. |
1425 {\it string\/}~{\tt <=}~{\it string}, associating each recursive set with |
1474 |
1426 its domain. |
1475 \item[\tt thy\_name] is a string, informing Isabelle's theory database of |
1427 |
1476 the name you will give to the result structure. |
1428 \item[\it introduction rules] specify one or more introduction rules in |
1477 |
1429 the form {\it ident\/}~{\it string}, where the identifier gives the name of |
1478 \item[\tt rec\_doms] is a list of pairs, associating the name of each recursive |
1430 the rule in the result structure. |
1479 set with its domain. |
1431 |
1480 |
1432 \item[\it monotonicity theorems] are required for each operator applied to |
1481 \item[\tt sintrs] specifies the desired introduction rules as strings. |
1433 a recursive set in the introduction rules. There {\bf must} be a theorem |
1482 |
1434 of the form $A\sbs B\Imp M(A)\sbs M(B)$, for each premise $t\in M(R_i)$ |
1483 \item[\tt monos] consists of monotonicity theorems for each operator applied |
1435 in an introduction rule! |
1484 to a recursive set in the introduction rules. |
1436 |
1485 |
1437 \item[\it constructor definitions] contain definitions of constants |
1486 \item[\tt con\_defs] contains definitions of constants appearing in the |
1438 appearing in the introduction rules. The (co)datatype package supplies |
1487 introduction rules. The (co)datatype package supplies the constructors' |
1439 the constructors' definitions here. Most (co)inductive definitions omit |
1488 definitions here. Most direct calls of \verb|Inductive_Fun| or |
1440 this section; one exception is the primitive recursive functions example |
1489 \verb|CoInductive_Fun| pass the empty list; one exception is the primitive |
1441 (\S\ref{primrec-sec}). |
1490 recursive functions example (\S\ref{primrec-sec}). |
1442 |
1491 |
1443 \item[\it type\_intrs] consists of introduction rules for type-checking the |
1492 \item[\tt type\_intrs] consists of introduction rules for type-checking the |
|
1493 definition, as discussed in~\S\ref{basic-sec}. They are applied using |
1444 definition, as discussed in~\S\ref{basic-sec}. They are applied using |
1494 depth-first search; you can trace the proof by setting |
1445 depth-first search; you can trace the proof by setting |
|
1446 |
1495 \verb|trace_DEPTH_FIRST := true|. |
1447 \verb|trace_DEPTH_FIRST := true|. |
1496 |
1448 |
1497 \item[\tt type\_elims] consists of elimination rules for type-checking the |
1449 \item[\it type\_elims] consists of elimination rules for type-checking the |
1498 definition. They are presumed to be `safe' and are applied as much as |
1450 definition. They are presumed to be `safe' and are applied as much as |
1499 possible, prior to the {\tt type\_intrs} search. |
1451 possible, prior to the {\tt type\_intrs} search. |
1500 \end{description} |
1452 \end{description} |
|
1453 |
1501 The package has a few notable restrictions: |
1454 The package has a few notable restrictions: |
1502 \begin{itemize} |
1455 \begin{itemize} |
1503 \item The parent theory, {\tt thy}, must declare the recursive sets as |
1456 \item The theory must separately declare the recursive sets as |
1504 constants. You can extend a theory with new constants using {\tt |
1457 constants. |
1505 addconsts}, as illustrated in~\S\ref{ind-eg-sec}. If the inductive |
|
1506 definition also requires new concrete syntax, then it is simpler to |
|
1507 express the parent theory using a theory file. It is often convenient to |
|
1508 define an infix syntax for relations, say $a\prec b$ for $\pair{a,b}\in |
|
1509 R$. |
|
1510 |
1458 |
1511 \item The names of the recursive sets must be identifiers, not infix |
1459 \item The names of the recursive sets must be identifiers, not infix |
1512 operators. |
1460 operators. |
1513 |
1461 |
1514 \item Side-conditions must not be conjunctions. However, an introduction rule |
1462 \item Side-conditions must not be conjunctions. However, an introduction rule |
1515 may contain any number of side-conditions. |
1463 may contain any number of side-conditions. |
1516 \end{itemize} |
1464 \end{itemize} |
1517 |
1465 |
1518 |
1466 |
1519 \section{Datatype and codatatype definitions: users guide} |
1467 \section{Datatype and codatatype definitions: users guide} |
1520 The ML functors \verb|Datatype_Fun| and \verb|CoDatatype_Fun| define datatypes |
1468 This section explains how to include (co)datatype declarations in a theory |
1521 and codatatypes, invoking \verb|Datatype_Fun| and |
1469 file. |
1522 \verb|CoDatatype_Fun| to make the underlying (co)inductive definitions. |
|
1523 |
1470 |
1524 |
1471 |
1525 \subsection{The result structure} |
1472 \subsection{The result structure} |
1526 The result structure extends that of (co)inductive definitions |
1473 The result structure extends that of (co)inductive definitions |
1527 (Figure~\ref{def-result-fig}) with several additional items: |
1474 (Figure~\ref{def-result-fig}) with several additional items: |
1528 \begin{ttbox} |
1475 \begin{ttbox} |
1529 val con_thy : theory |
|
1530 val con_defs : thm list |
1476 val con_defs : thm list |
1531 val case_eqns : thm list |
1477 val case_eqns : thm list |
1532 val free_iffs : thm list |
1478 val free_iffs : thm list |
1533 val free_SEs : thm list |
1479 val free_SEs : thm list |
1534 val mk_free : string -> thm |
1480 val mk_free : string -> thm |
1535 \end{ttbox} |
1481 \end{ttbox} |
1536 Most of these have been discussed in~\S\ref{data-sec}. Here is a summary: |
1482 Most of these have been discussed in~\S\ref{data-sec}. Here is a summary: |
1537 \begin{description} |
1483 \begin{description} |
1538 \item[\tt con\_thy] is a new theory containing definitions of the |
|
1539 (co)datatype's constructors and case operator. It also declares the |
|
1540 recursive sets as constants, so that it may serve as the parent |
|
1541 theory for the (co)inductive definition. |
|
1542 |
|
1543 \item[\tt con\_defs] is a list of definitions: the case operator followed by |
1484 \item[\tt con\_defs] is a list of definitions: the case operator followed by |
1544 the constructors. This theorem list can be supplied to \verb|mk_cases|, for |
1485 the constructors. This theorem list can be supplied to \verb|mk_cases|, for |
1545 example. |
1486 example. |
1546 |
1487 |
1547 \item[\tt case\_eqns] is a list of equations, stating that the case operator |
1488 \item[\tt case\_eqns] is a list of equations, stating that the case operator |
1568 The result structure also inherits everything from the underlying |
1509 The result structure also inherits everything from the underlying |
1569 (co)inductive definition, such as the introduction rules, elimination rule, |
1510 (co)inductive definition, such as the introduction rules, elimination rule, |
1570 and (co)induction rule. |
1511 and (co)induction rule. |
1571 |
1512 |
1572 |
1513 |
1573 \begin{figure} |
1514 \subsection{The syntax of a (co)datatype definition} |
|
1515 A datatype definition has the form |
1574 \begin{ttbox} |
1516 \begin{ttbox} |
1575 sig |
1517 datatype <={\it domain} |
1576 val thy : theory |
1518 {\it datatype declaration} and {\it datatype declaration} and \ldots |
1577 val thy_name : string |
1519 monos {\it monotonicity theorems} |
1578 val rec_specs : (string * string * (string list*string)list) list |
1520 type_intrs {\it introduction rules for type-checking} |
1579 val rec_styp : string |
1521 type_elims {\it elimination rules for type-checking} |
1580 val sintrs : string list |
|
1581 val monos : thm list |
|
1582 val type_intrs: thm list |
|
1583 val type_elims: thm list |
|
1584 end |
|
1585 \end{ttbox} |
1522 \end{ttbox} |
1586 \hrule |
1523 A codatatype definition is identical save that it starts with the keyword |
1587 \caption{The argument of a (co)datatype definition} \label{data-arg-fig} |
1524 {\tt codatatype}. The syntax is rather complicated; please consult the |
1588 \end{figure} |
1525 examples above (\S\ref{lists-sec}) and the theory files on the ZF source |
1589 |
1526 directory. |
1590 \subsection{The argument structure} |
1527 |
1591 Both (co)datatype functors take the same argument structure |
1528 The {\tt monos}, {\tt type\_intrs} and {\tt type\_elims} sections are |
1592 (Figure~\ref{data-arg-fig}). It does not extend that for (co)inductive |
1529 optional. They are treated like their counterparts in a (co)inductive |
1593 definitions, but shares several components and passes them uninterpreted to |
1530 definition, as described above. The package supplements your type-checking |
1594 \verb|Datatype_Fun| or \verb|CoDatatype_Fun|. The new components are as |
1531 rules (if any) with additional ones that should cope with any |
1595 follows: |
1532 finitely-branching (co)datatype definition. |
|
1533 |
1596 \begin{description} |
1534 \begin{description} |
1597 \item[\tt thy] is the (co)datatype's parent theory. It {\it must not\/} |
1535 \item[\it domain] specifies a single domain to use for all the mutually |
1598 declare constants for the recursive sets. Recall that (co)inductive |
1536 recursive (co)datatypes. If it (and the preceeding~{\tt <=}) are |
1599 definitions have the opposite restriction. |
1537 omitted, the package supplies a domain automatically. Suppose the |
1600 |
1538 definition involves the set parameters $A_1$, \ldots, $A_k$. Then |
1601 \item[\tt rec\_specs] is a list of triples of the form ({\it recursive set\/}, |
1539 $\univ(A_1\un\cdots\un A_k)$ is used for a datatype definition and |
1602 {\it domain\/}, {\it constructors\/}) for each mutually recursive set. {\it |
1540 $\quniv(A_1\un\cdots\un A_k)$ is used for a codatatype definition. |
1603 Constructors\/} is a list of the form (names, type, mixfix). The mixfix |
1541 |
1604 component is usually {\tt NoSyn}, specifying no special syntax for the |
1542 These choices should work for all finitely-branching (co)datatype |
1605 constructor; other useful possibilities are {\tt Infixl}~$p$ and {\tt |
1543 definitions. For examples of infinitely-branching datatype |
1606 Infixr}~$p$, specifying an infix operator of priority~$p$. |
1544 definitions, see the file {\tt ZF/ex/Brouwer.thy}. |
1607 Section~\ref{data-sec} presents examples. |
1545 |
1608 |
1546 \item[\it datatype declaration] has the form |
1609 \item[\tt rec\_styp] is the common meta-type of the mutually recursive sets, |
1547 \begin{quote} |
1610 specified as a string. They must all have the same type because all must |
1548 {\it string\/} {\tt =} {\it constructor} {\tt|} {\it constructor} {\tt|} |
1611 take the same parameters. |
1549 \ldots |
|
1550 \end{quote} |
|
1551 The {\it string\/} is the datatype, say {\tt"list(A)"}. Each |
|
1552 {\it constructor\/} has the form |
|
1553 \begin{quote} |
|
1554 {\it name\/} {\tt(} {\it premise} {\tt,} {\it premise} {\tt,} \ldots {\tt)} |
|
1555 {\it mixfix\/} |
|
1556 \end{quote} |
|
1557 The {\it name\/} specifies a new constructor while the {\it premises\/} its |
|
1558 typing conditions. The optional {\it mixfix\/} phrase may give |
|
1559 the constructor infix, for example. |
|
1560 |
|
1561 Mutually recursive {\it datatype declarations\/} are separated by the |
|
1562 keyword~{\tt and}. |
1612 \end{description} |
1563 \end{description} |
1613 The choice of domain is usually simple. Isabelle/ZF defines the set |
1564 |
1614 $\univ(A)$, which contains~$A$ and is closed under the standard Cartesian |
1565 \paragraph*{Note.} |
1615 products and disjoint sums \cite[\S4.2]{paulson-set-II}. In a typical |
1566 In the definitions of the constructors, the right-hand sides may overlap. |
1616 datatype definition with set parameters $A_1$, \ldots, $A_k$, a suitable |
1567 For instance, the datatype of combinators has constructors defined by |
1617 domain for all the recursive sets is $\univ(A_1\un\cdots\un A_k)$. For a |
|
1618 codatatype definition, the set |
|
1619 $\quniv(A)$ contains~$A$ and is closed under the variant Cartesian products |
|
1620 and disjoint sums; the appropriate domain is |
|
1621 $\quniv(A_1\un\cdots\un A_k)$. |
|
1622 |
|
1623 The {\tt sintrs} specify the introduction rules, which govern the recursive |
|
1624 structure of the datatype. Introduction rules may involve monotone |
|
1625 operators and side-conditions to express things that go beyond the usual |
|
1626 notion of datatype. The theorem lists {\tt monos}, {\tt type\_intrs} and |
|
1627 {\tt type\_elims} should contain precisely what is needed for the |
|
1628 underlying (co)inductive definition. Isabelle/ZF defines lists of |
|
1629 type-checking rules that can be supplied for the latter two components: |
|
1630 \begin{itemize} |
|
1631 \item {\tt datatype\_intrs} and {\tt datatype\_elims} are rules |
|
1632 for $\univ(A)$. |
|
1633 \item {\tt codatatype\_intrs} and {\tt codatatype\_elims} are |
|
1634 rules for $\quniv(A)$. |
|
1635 \end{itemize} |
|
1636 In typical definitions, these theorem lists need not be supplemented with |
|
1637 other theorems. |
|
1638 |
|
1639 The constructor definitions' right-hand sides can overlap. A |
|
1640 simple example is the datatype for the combinators, whose constructors are |
|
1641 \begin{eqnarray*} |
1568 \begin{eqnarray*} |
1642 {\tt K} & \equiv & \Inl(\emptyset) \\ |
1569 {\tt K} & \equiv & \Inl(\emptyset) \\ |
1643 {\tt S} & \equiv & \Inr(\Inl(\emptyset)) \\ |
1570 {\tt S} & \equiv & \Inr(\Inl(\emptyset)) \\ |
1644 p{\tt\#}q & \equiv & \Inr(\Inl(\pair{p,q})) |
1571 p{\tt\#}q & \equiv & \Inr(\Inl(\pair{p,q})) |
1645 \end{eqnarray*} |
1572 \end{eqnarray*} |