9722
|
1 |
%
|
|
2 |
\begin{isabellebody}%
|
9924
|
3 |
\def\isabellecontext{Nested}%
|
17056
|
4 |
%
|
|
5 |
\isadelimtheory
|
|
6 |
%
|
|
7 |
\endisadelimtheory
|
|
8 |
%
|
|
9 |
\isatagtheory
|
|
10 |
%
|
|
11 |
\endisatagtheory
|
|
12 |
{\isafoldtheory}%
|
|
13 |
%
|
|
14 |
\isadelimtheory
|
|
15 |
%
|
|
16 |
\endisadelimtheory
|
8749
|
17 |
%
|
|
18 |
\begin{isamarkuptext}%
|
11458
|
19 |
\index{datatypes!and nested recursion}%
|
8749
|
20 |
So far, all datatypes had the property that on the right-hand side of their
|
11458
|
21 |
definition they occurred only at the top-level: directly below a
|
11256
|
22 |
constructor. Now we consider \emph{nested recursion}, where the recursive
|
11310
|
23 |
datatype occurs nested in some other datatype (but not inside itself!).
|
11256
|
24 |
Consider the following model of terms
|
8749
|
25 |
where function symbols can be applied to a list of arguments:%
|
|
26 |
\end{isamarkuptext}%
|
17175
|
27 |
\isamarkuptrue%
|
|
28 |
\isacommand{datatype}\isamarkupfalse%
|
|
29 |
\ {\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}{\isachardoublequoteopen}term{\isachardoublequoteclose}\ {\isacharequal}\ Var\ {\isacharprime}v\ {\isacharbar}\ App\ {\isacharprime}f\ {\isachardoublequoteopen}{\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term\ list{\isachardoublequoteclose}%
|
8749
|
30 |
\begin{isamarkuptext}%
|
|
31 |
\noindent
|
|
32 |
Note that we need to quote \isa{term} on the left to avoid confusion with
|
10171
|
33 |
the Isabelle command \isacommand{term}.
|
10971
|
34 |
Parameter \isa{{\isacharprime}v} is the type of variables and \isa{{\isacharprime}f} the type of
|
8749
|
35 |
function symbols.
|
9933
|
36 |
A mathematical term like $f(x,g(y))$ becomes \isa{App\ f\ {\isacharbrackleft}Var\ x{\isacharcomma}\ App\ g\ {\isacharbrackleft}Var\ y{\isacharbrackright}{\isacharbrackright}}, where \isa{f}, \isa{g}, \isa{x}, \isa{y} are
|
8749
|
37 |
suitable values, e.g.\ numbers or strings.
|
|
38 |
|
|
39 |
What complicates the definition of \isa{term} is the nested occurrence of
|
|
40 |
\isa{term} inside \isa{list} on the right-hand side. In principle,
|
|
41 |
nested recursion can be eliminated in favour of mutual recursion by unfolding
|
|
42 |
the offending datatypes, here \isa{list}. The result for \isa{term}
|
|
43 |
would be something like
|
8751
|
44 |
\medskip
|
|
45 |
|
|
46 |
\input{Datatype/document/unfoldnested.tex}
|
|
47 |
\medskip
|
|
48 |
|
|
49 |
\noindent
|
8749
|
50 |
Although we do not recommend this unfolding to the user, it shows how to
|
|
51 |
simulate nested recursion by mutual recursion.
|
|
52 |
Now we return to the initial definition of \isa{term} using
|
|
53 |
nested recursion.
|
|
54 |
|
|
55 |
Let us define a substitution function on terms. Because terms involve term
|
|
56 |
lists, we need to define two substitution functions simultaneously:%
|
|
57 |
\end{isamarkuptext}%
|
17175
|
58 |
\isamarkuptrue%
|
|
59 |
\isacommand{consts}\isamarkupfalse%
|
|
60 |
\isanewline
|
|
61 |
subst\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}{\isacharparenleft}{\isacharprime}v{\isasymRightarrow}{\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term{\isacharparenright}\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term\ \ \ \ \ \ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term{\isachardoublequoteclose}\isanewline
|
|
62 |
substs{\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}{\isacharparenleft}{\isacharprime}v{\isasymRightarrow}{\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term{\isacharparenright}\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term\ list\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term\ list{\isachardoublequoteclose}\isanewline
|
8749
|
63 |
\isanewline
|
17175
|
64 |
\isacommand{primrec}\isamarkupfalse%
|
|
65 |
\isanewline
|
|
66 |
\ \ {\isachardoublequoteopen}subst\ s\ {\isacharparenleft}Var\ x{\isacharparenright}\ {\isacharequal}\ s\ x{\isachardoublequoteclose}\isanewline
|
9698
|
67 |
\ \ subst{\isacharunderscore}App{\isacharcolon}\isanewline
|
17175
|
68 |
\ \ {\isachardoublequoteopen}subst\ s\ {\isacharparenleft}App\ f\ ts{\isacharparenright}\ {\isacharequal}\ App\ f\ {\isacharparenleft}substs\ s\ ts{\isacharparenright}{\isachardoublequoteclose}\isanewline
|
8749
|
69 |
\isanewline
|
17175
|
70 |
\ \ {\isachardoublequoteopen}substs\ s\ {\isacharbrackleft}{\isacharbrackright}\ {\isacharequal}\ {\isacharbrackleft}{\isacharbrackright}{\isachardoublequoteclose}\isanewline
|
|
71 |
\ \ {\isachardoublequoteopen}substs\ s\ {\isacharparenleft}t\ {\isacharhash}\ ts{\isacharparenright}\ {\isacharequal}\ subst\ s\ t\ {\isacharhash}\ substs\ s\ ts{\isachardoublequoteclose}%
|
8749
|
72 |
\begin{isamarkuptext}%
|
|
73 |
\noindent
|
11458
|
74 |
Individual equations in a \commdx{primrec} definition may be
|
|
75 |
named as shown for \isa{subst{\isacharunderscore}App}.
|
10171
|
76 |
The significance of this device will become apparent below.
|
9644
|
77 |
|
8749
|
78 |
Similarly, when proving a statement about terms inductively, we need
|
|
79 |
to prove a related statement about term lists simultaneously. For example,
|
|
80 |
the fact that the identity substitution does not change a term needs to be
|
|
81 |
strengthened and proved as follows:%
|
|
82 |
\end{isamarkuptext}%
|
17175
|
83 |
\isamarkuptrue%
|
|
84 |
\isacommand{lemma}\isamarkupfalse%
|
|
85 |
\ subst{\isacharunderscore}id{\isacharcolon}\ {\isachardoublequoteopen}subst\ \ Var\ t\ \ {\isacharequal}\ {\isacharparenleft}t\ {\isacharcolon}{\isacharcolon}{\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term{\isacharparenright}\ \ {\isasymand}\isanewline
|
|
86 |
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ substs\ Var\ ts\ {\isacharequal}\ {\isacharparenleft}ts{\isacharcolon}{\isacharcolon}{\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}term\ list{\isacharparenright}{\isachardoublequoteclose}\isanewline
|
17056
|
87 |
%
|
|
88 |
\isadelimproof
|
|
89 |
%
|
|
90 |
\endisadelimproof
|
|
91 |
%
|
|
92 |
\isatagproof
|
17175
|
93 |
\isacommand{apply}\isamarkupfalse%
|
|
94 |
{\isacharparenleft}induct{\isacharunderscore}tac\ t\ \isakeyword{and}\ ts{\isacharcomma}\ simp{\isacharunderscore}all{\isacharparenright}\isanewline
|
|
95 |
\isacommand{done}\isamarkupfalse%
|
|
96 |
%
|
17056
|
97 |
\endisatagproof
|
|
98 |
{\isafoldproof}%
|
|
99 |
%
|
|
100 |
\isadelimproof
|
|
101 |
%
|
|
102 |
\endisadelimproof
|
11866
|
103 |
%
|
8749
|
104 |
\begin{isamarkuptext}%
|
|
105 |
\noindent
|
9933
|
106 |
Note that \isa{Var} is the identity substitution because by definition it
|
|
107 |
leaves variables unchanged: \isa{subst\ Var\ {\isacharparenleft}Var\ x{\isacharparenright}\ {\isacharequal}\ Var\ x}. Note also
|
8749
|
108 |
that the type annotations are necessary because otherwise there is nothing in
|
|
109 |
the goal to enforce that both halves of the goal talk about the same type
|
10971
|
110 |
parameters \isa{{\isacharparenleft}{\isacharprime}v{\isacharcomma}{\isacharprime}f{\isacharparenright}}. As a result, induction would fail
|
8749
|
111 |
because the two halves of the goal would be unrelated.
|
|
112 |
|
|
113 |
\begin{exercise}
|
|
114 |
The fact that substitution distributes over composition can be expressed
|
|
115 |
roughly as follows:
|
9792
|
116 |
\begin{isabelle}%
|
10178
|
117 |
\ \ \ \ \ subst\ {\isacharparenleft}f\ {\isasymcirc}\ g{\isacharparenright}\ t\ {\isacharequal}\ subst\ f\ {\isacharparenleft}subst\ g\ t{\isacharparenright}%
|
9924
|
118 |
\end{isabelle}
|
8749
|
119 |
Correct this statement (you will find that it does not type-check),
|
10178
|
120 |
strengthen it, and prove it. (Note: \isa{{\isasymcirc}} is function composition;
|
9792
|
121 |
its definition is found in theorem \isa{o{\isacharunderscore}def}).
|
8749
|
122 |
\end{exercise}
|
9644
|
123 |
\begin{exercise}\label{ex:trev-trev}
|
10971
|
124 |
Define a function \isa{trev} of type \isa{{\isacharparenleft}{\isacharprime}v{\isacharcomma}\ {\isacharprime}f{\isacharparenright}\ term\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}v{\isacharcomma}\ {\isacharprime}f{\isacharparenright}\ term}
|
9792
|
125 |
that recursively reverses the order of arguments of all function symbols in a
|
|
126 |
term. Prove that \isa{trev\ {\isacharparenleft}trev\ t{\isacharparenright}\ {\isacharequal}\ t}.
|
9644
|
127 |
\end{exercise}
|
|
128 |
|
10795
|
129 |
The experienced functional programmer may feel that our definition of
|
|
130 |
\isa{subst} is too complicated in that \isa{substs} is
|
|
131 |
unnecessary. The \isa{App}-case can be defined directly as
|
9644
|
132 |
\begin{isabelle}%
|
9834
|
133 |
\ \ \ \ \ subst\ s\ {\isacharparenleft}App\ f\ ts{\isacharparenright}\ {\isacharequal}\ App\ f\ {\isacharparenleft}map\ {\isacharparenleft}subst\ s{\isacharparenright}\ ts{\isacharparenright}%
|
9924
|
134 |
\end{isabelle}
|
9644
|
135 |
where \isa{map} is the standard list function such that
|
10187
|
136 |
\isa{map\ f\ {\isacharbrackleft}x{\isadigit{1}}{\isacharcomma}{\isachardot}{\isachardot}{\isachardot}{\isacharcomma}xn{\isacharbrackright}\ {\isacharequal}\ {\isacharbrackleft}f\ x{\isadigit{1}}{\isacharcomma}{\isachardot}{\isachardot}{\isachardot}{\isacharcomma}f\ xn{\isacharbrackright}}. This is true, but Isabelle
|
10795
|
137 |
insists on the conjunctive format. Fortunately, we can easily \emph{prove}
|
9792
|
138 |
that the suggested equation holds:%
|
9644
|
139 |
\end{isamarkuptext}%
|
17175
|
140 |
\isamarkuptrue%
|
17056
|
141 |
%
|
|
142 |
\isadelimproof
|
|
143 |
%
|
|
144 |
\endisadelimproof
|
|
145 |
%
|
|
146 |
\isatagproof
|
|
147 |
%
|
|
148 |
\endisatagproof
|
|
149 |
{\isafoldproof}%
|
|
150 |
%
|
|
151 |
\isadelimproof
|
|
152 |
%
|
|
153 |
\endisadelimproof
|
|
154 |
%
|
|
155 |
\isadelimproof
|
|
156 |
%
|
|
157 |
\endisadelimproof
|
|
158 |
%
|
|
159 |
\isatagproof
|
17175
|
160 |
%
|
|
161 |
\endisatagproof
|
|
162 |
{\isafoldproof}%
|
|
163 |
%
|
|
164 |
\isadelimproof
|
|
165 |
%
|
|
166 |
\endisadelimproof
|
|
167 |
%
|
|
168 |
\isadelimproof
|
|
169 |
%
|
|
170 |
\endisadelimproof
|
|
171 |
%
|
|
172 |
\isatagproof
|
|
173 |
%
|
|
174 |
\endisatagproof
|
|
175 |
{\isafoldproof}%
|
|
176 |
%
|
|
177 |
\isadelimproof
|
|
178 |
\isanewline
|
|
179 |
%
|
|
180 |
\endisadelimproof
|
|
181 |
\isacommand{lemma}\isamarkupfalse%
|
|
182 |
\ {\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\ {\isachardoublequoteopen}subst\ s\ {\isacharparenleft}App\ f\ ts{\isacharparenright}\ {\isacharequal}\ App\ f\ {\isacharparenleft}map\ {\isacharparenleft}subst\ s{\isacharparenright}\ ts{\isacharparenright}{\isachardoublequoteclose}\isanewline
|
|
183 |
%
|
|
184 |
\isadelimproof
|
|
185 |
%
|
|
186 |
\endisadelimproof
|
|
187 |
%
|
|
188 |
\isatagproof
|
|
189 |
\isacommand{apply}\isamarkupfalse%
|
|
190 |
{\isacharparenleft}induct{\isacharunderscore}tac\ ts{\isacharcomma}\ simp{\isacharunderscore}all{\isacharparenright}\isanewline
|
|
191 |
\isacommand{done}\isamarkupfalse%
|
17056
|
192 |
%
|
|
193 |
\endisatagproof
|
|
194 |
{\isafoldproof}%
|
|
195 |
%
|
|
196 |
\isadelimproof
|
|
197 |
%
|
|
198 |
\endisadelimproof
|
|
199 |
%
|
9644
|
200 |
\begin{isamarkuptext}%
|
9689
|
201 |
\noindent
|
9644
|
202 |
What is more, we can now disable the old defining equation as a
|
|
203 |
simplification rule:%
|
|
204 |
\end{isamarkuptext}%
|
17175
|
205 |
\isamarkuptrue%
|
|
206 |
\isacommand{declare}\isamarkupfalse%
|
|
207 |
\ subst{\isacharunderscore}App\ {\isacharbrackleft}simp\ del{\isacharbrackright}%
|
9644
|
208 |
\begin{isamarkuptext}%
|
|
209 |
\noindent
|
9689
|
210 |
The advantage is that now we have replaced \isa{substs} by
|
|
211 |
\isa{map}, we can profit from the large number of pre-proved lemmas
|
|
212 |
about \isa{map}. Unfortunately inductive proofs about type
|
|
213 |
\isa{term} are still awkward because they expect a conjunction. One
|
|
214 |
could derive a new induction principle as well (see
|
10795
|
215 |
\S\ref{sec:derive-ind}), but simpler is to stop using \isacommand{primrec}
|
|
216 |
and to define functions with \isacommand{recdef} instead.
|
11309
|
217 |
Simple uses of \isacommand{recdef} are described in \S\ref{sec:recdef} below,
|
|
218 |
and later (\S\ref{sec:nested-recdef}) we shall see how \isacommand{recdef} can
|
|
219 |
handle nested recursion.
|
8749
|
220 |
|
10971
|
221 |
Of course, you may also combine mutual and nested recursion of datatypes. For example,
|
8749
|
222 |
constructor \isa{Sum} in \S\ref{sec:datatype-mut-rec} could take a list of
|
9792
|
223 |
expressions as its argument: \isa{Sum}~\isa{{\isachardoublequote}{\isacharprime}a\ aexp\ list{\isachardoublequote}}.%
|
8749
|
224 |
\end{isamarkuptext}%
|
17175
|
225 |
\isamarkuptrue%
|
17056
|
226 |
%
|
|
227 |
\isadelimtheory
|
|
228 |
%
|
|
229 |
\endisadelimtheory
|
|
230 |
%
|
|
231 |
\isatagtheory
|
|
232 |
%
|
|
233 |
\endisatagtheory
|
|
234 |
{\isafoldtheory}%
|
|
235 |
%
|
|
236 |
\isadelimtheory
|
|
237 |
%
|
|
238 |
\endisadelimtheory
|
9722
|
239 |
\end{isabellebody}%
|
9145
|
240 |
%%% Local Variables:
|
|
241 |
%%% mode: latex
|
|
242 |
%%% TeX-master: "root"
|
|
243 |
%%% End:
|