wenzelm@30081
|
1 |
theory Proof
|
wenzelm@30081
|
2 |
imports Base
|
wenzelm@30081
|
3 |
begin
|
wenzelm@18537
|
4 |
|
wenzelm@20451
|
5 |
chapter {* Structured proofs *}
|
wenzelm@18537
|
6 |
|
wenzelm@20474
|
7 |
section {* Variables \label{sec:variables} *}
|
wenzelm@20026
|
8 |
|
wenzelm@20470
|
9 |
text {*
|
wenzelm@20470
|
10 |
Any variable that is not explicitly bound by @{text "\<lambda>"}-abstraction
|
wenzelm@20470
|
11 |
is considered as ``free''. Logically, free variables act like
|
wenzelm@20474
|
12 |
outermost universal quantification at the sequent level: @{text
|
wenzelm@20470
|
13 |
"A\<^isub>1(x), \<dots>, A\<^isub>n(x) \<turnstile> B(x)"} means that the result
|
wenzelm@20470
|
14 |
holds \emph{for all} values of @{text "x"}. Free variables for
|
wenzelm@20470
|
15 |
terms (not types) can be fully internalized into the logic: @{text
|
wenzelm@20474
|
16 |
"\<turnstile> B(x)"} and @{text "\<turnstile> \<And>x. B(x)"} are interchangeable, provided
|
wenzelm@20474
|
17 |
that @{text "x"} does not occur elsewhere in the context.
|
wenzelm@20474
|
18 |
Inspecting @{text "\<turnstile> \<And>x. B(x)"} more closely, we see that inside the
|
wenzelm@20470
|
19 |
quantifier, @{text "x"} is essentially ``arbitrary, but fixed'',
|
wenzelm@20470
|
20 |
while from outside it appears as a place-holder for instantiation
|
wenzelm@20474
|
21 |
(thanks to @{text "\<And>"} elimination).
|
wenzelm@20470
|
22 |
|
wenzelm@20474
|
23 |
The Pure logic represents the idea of variables being either inside
|
wenzelm@20474
|
24 |
or outside the current scope by providing separate syntactic
|
wenzelm@20470
|
25 |
categories for \emph{fixed variables} (e.g.\ @{text "x"}) vs.\
|
wenzelm@20470
|
26 |
\emph{schematic variables} (e.g.\ @{text "?x"}). Incidently, a
|
wenzelm@20474
|
27 |
universal result @{text "\<turnstile> \<And>x. B(x)"} has the HHF normal form @{text
|
wenzelm@34997
|
28 |
"\<turnstile> B(?x)"}, which represents its generality without requiring an
|
wenzelm@34997
|
29 |
explicit quantifier. The same principle works for type variables:
|
wenzelm@34997
|
30 |
@{text "\<turnstile> B(?\<alpha>)"} represents the idea of ``@{text "\<turnstile> \<forall>\<alpha>. B(\<alpha>)"}''
|
wenzelm@34997
|
31 |
without demanding a truly polymorphic framework.
|
wenzelm@20470
|
32 |
|
wenzelm@20470
|
33 |
\medskip Additional care is required to treat type variables in a
|
wenzelm@20470
|
34 |
way that facilitates type-inference. In principle, term variables
|
wenzelm@20470
|
35 |
depend on type variables, which means that type variables would have
|
wenzelm@20470
|
36 |
to be declared first. For example, a raw type-theoretic framework
|
wenzelm@20470
|
37 |
would demand the context to be constructed in stages as follows:
|
wenzelm@20470
|
38 |
@{text "\<Gamma> = \<alpha>: type, x: \<alpha>, a: A(x\<^isub>\<alpha>)"}.
|
wenzelm@20470
|
39 |
|
wenzelm@20470
|
40 |
We allow a slightly less formalistic mode of operation: term
|
wenzelm@20470
|
41 |
variables @{text "x"} are fixed without specifying a type yet
|
wenzelm@20470
|
42 |
(essentially \emph{all} potential occurrences of some instance
|
wenzelm@20474
|
43 |
@{text "x\<^isub>\<tau>"} are fixed); the first occurrence of @{text "x"}
|
wenzelm@20474
|
44 |
within a specific term assigns its most general type, which is then
|
wenzelm@20474
|
45 |
maintained consistently in the context. The above example becomes
|
wenzelm@20474
|
46 |
@{text "\<Gamma> = x: term, \<alpha>: type, A(x\<^isub>\<alpha>)"}, where type @{text
|
wenzelm@20474
|
47 |
"\<alpha>"} is fixed \emph{after} term @{text "x"}, and the constraint
|
wenzelm@20474
|
48 |
@{text "x :: \<alpha>"} is an implicit consequence of the occurrence of
|
wenzelm@20474
|
49 |
@{text "x\<^isub>\<alpha>"} in the subsequent proposition.
|
wenzelm@20470
|
50 |
|
wenzelm@20470
|
51 |
This twist of dependencies is also accommodated by the reverse
|
wenzelm@20470
|
52 |
operation of exporting results from a context: a type variable
|
wenzelm@20470
|
53 |
@{text "\<alpha>"} is considered fixed as long as it occurs in some fixed
|
wenzelm@20470
|
54 |
term variable of the context. For example, exporting @{text "x:
|
wenzelm@20474
|
55 |
term, \<alpha>: type \<turnstile> x\<^isub>\<alpha> = x\<^isub>\<alpha>"} produces in the first step
|
wenzelm@20474
|
56 |
@{text "x: term \<turnstile> x\<^isub>\<alpha> = x\<^isub>\<alpha>"} for fixed @{text "\<alpha>"},
|
wenzelm@20474
|
57 |
and only in the second step @{text "\<turnstile> ?x\<^isub>?\<^isub>\<alpha> =
|
wenzelm@20474
|
58 |
?x\<^isub>?\<^isub>\<alpha>"} for schematic @{text "?x"} and @{text "?\<alpha>"}.
|
wenzelm@20470
|
59 |
|
wenzelm@20470
|
60 |
\medskip The Isabelle/Isar proof context manages the gory details of
|
wenzelm@20470
|
61 |
term vs.\ type variables, with high-level principles for moving the
|
wenzelm@20474
|
62 |
frontier between fixed and schematic variables.
|
wenzelm@20470
|
63 |
|
wenzelm@20474
|
64 |
The @{text "add_fixes"} operation explictly declares fixed
|
wenzelm@20474
|
65 |
variables; the @{text "declare_term"} operation absorbs a term into
|
wenzelm@20474
|
66 |
a context by fixing new type variables and adding syntactic
|
wenzelm@20474
|
67 |
constraints.
|
wenzelm@20474
|
68 |
|
wenzelm@20474
|
69 |
The @{text "export"} operation is able to perform the main work of
|
wenzelm@20474
|
70 |
generalizing term and type variables as sketched above, assuming
|
wenzelm@20474
|
71 |
that fixing variables and terms have been declared properly.
|
wenzelm@20474
|
72 |
|
wenzelm@20474
|
73 |
There @{text "import"} operation makes a generalized fact a genuine
|
wenzelm@20474
|
74 |
part of the context, by inventing fixed variables for the schematic
|
wenzelm@20474
|
75 |
ones. The effect can be reversed by using @{text "export"} later,
|
wenzelm@20474
|
76 |
potentially with an extended context; the result is equivalent to
|
wenzelm@20474
|
77 |
the original modulo renaming of schematic variables.
|
wenzelm@20470
|
78 |
|
wenzelm@20470
|
79 |
The @{text "focus"} operation provides a variant of @{text "import"}
|
wenzelm@20470
|
80 |
for nested propositions (with explicit quantification): @{text
|
wenzelm@20474
|
81 |
"\<And>x\<^isub>1 \<dots> x\<^isub>n. B(x\<^isub>1, \<dots>, x\<^isub>n)"} is
|
wenzelm@20474
|
82 |
decomposed by inventing fixed variables @{text "x\<^isub>1, \<dots>,
|
wenzelm@20474
|
83 |
x\<^isub>n"} for the body.
|
wenzelm@20470
|
84 |
*}
|
wenzelm@20064
|
85 |
|
wenzelm@20026
|
86 |
text %mlref {*
|
wenzelm@20026
|
87 |
\begin{mldecls}
|
wenzelm@20474
|
88 |
@{index_ML Variable.add_fixes: "
|
wenzelm@20474
|
89 |
string list -> Proof.context -> string list * Proof.context"} \\
|
wenzelm@20797
|
90 |
@{index_ML Variable.variant_fixes: "
|
wenzelm@20474
|
91 |
string list -> Proof.context -> string list * Proof.context"} \\
|
wenzelm@20026
|
92 |
@{index_ML Variable.declare_term: "term -> Proof.context -> Proof.context"} \\
|
wenzelm@20470
|
93 |
@{index_ML Variable.declare_constraints: "term -> Proof.context -> Proof.context"} \\
|
wenzelm@20470
|
94 |
@{index_ML Variable.export: "Proof.context -> Proof.context -> thm list -> thm list"} \\
|
wenzelm@20470
|
95 |
@{index_ML Variable.polymorphic: "Proof.context -> term list -> term list"} \\
|
wenzelm@31794
|
96 |
@{index_ML Variable.import: "bool -> thm list -> Proof.context ->
|
wenzelm@32302
|
97 |
(((ctyp * ctyp) list * (cterm * cterm) list) * thm list) * Proof.context"} \\
|
wenzelm@34997
|
98 |
@{index_ML Variable.focus: "cterm -> Proof.context ->
|
wenzelm@34997
|
99 |
((string * cterm) list * cterm) * Proof.context"} \\
|
wenzelm@20026
|
100 |
\end{mldecls}
|
wenzelm@20026
|
101 |
|
wenzelm@20026
|
102 |
\begin{description}
|
wenzelm@20026
|
103 |
|
wenzelm@20064
|
104 |
\item @{ML Variable.add_fixes}~@{text "xs ctxt"} fixes term
|
wenzelm@20470
|
105 |
variables @{text "xs"}, returning the resulting internal names. By
|
wenzelm@20470
|
106 |
default, the internal representation coincides with the external
|
wenzelm@20474
|
107 |
one, which also means that the given variables must not be fixed
|
wenzelm@20474
|
108 |
already. There is a different policy within a local proof body: the
|
wenzelm@20474
|
109 |
given names are just hints for newly invented Skolem variables.
|
wenzelm@20026
|
110 |
|
wenzelm@20797
|
111 |
\item @{ML Variable.variant_fixes} is similar to @{ML
|
wenzelm@20470
|
112 |
Variable.add_fixes}, but always produces fresh variants of the given
|
wenzelm@20474
|
113 |
names.
|
wenzelm@20064
|
114 |
|
wenzelm@20470
|
115 |
\item @{ML Variable.declare_term}~@{text "t ctxt"} declares term
|
wenzelm@20470
|
116 |
@{text "t"} to belong to the context. This automatically fixes new
|
wenzelm@20470
|
117 |
type variables, but not term variables. Syntactic constraints for
|
wenzelm@20474
|
118 |
type and term variables are declared uniformly, though.
|
wenzelm@20470
|
119 |
|
wenzelm@20474
|
120 |
\item @{ML Variable.declare_constraints}~@{text "t ctxt"} declares
|
wenzelm@20474
|
121 |
syntactic constraints from term @{text "t"}, without making it part
|
wenzelm@20474
|
122 |
of the context yet.
|
wenzelm@20470
|
123 |
|
wenzelm@20470
|
124 |
\item @{ML Variable.export}~@{text "inner outer thms"} generalizes
|
wenzelm@20470
|
125 |
fixed type and term variables in @{text "thms"} according to the
|
wenzelm@20470
|
126 |
difference of the @{text "inner"} and @{text "outer"} context,
|
wenzelm@20470
|
127 |
following the principles sketched above.
|
wenzelm@20470
|
128 |
|
wenzelm@20470
|
129 |
\item @{ML Variable.polymorphic}~@{text "ctxt ts"} generalizes type
|
wenzelm@20470
|
130 |
variables in @{text "ts"} as far as possible, even those occurring
|
wenzelm@20470
|
131 |
in fixed term variables. The default policy of type-inference is to
|
wenzelm@20474
|
132 |
fix newly introduced type variables, which is essentially reversed
|
wenzelm@20474
|
133 |
with @{ML Variable.polymorphic}: here the given terms are detached
|
wenzelm@20474
|
134 |
from the context as far as possible.
|
wenzelm@20470
|
135 |
|
wenzelm@31794
|
136 |
\item @{ML Variable.import}~@{text "open thms ctxt"} invents fixed
|
wenzelm@20474
|
137 |
type and term variables for the schematic ones occurring in @{text
|
wenzelm@20474
|
138 |
"thms"}. The @{text "open"} flag indicates whether the fixed names
|
wenzelm@20474
|
139 |
should be accessible to the user, otherwise newly introduced names
|
wenzelm@20474
|
140 |
are marked as ``internal'' (\secref{sec:names}).
|
wenzelm@20064
|
141 |
|
wenzelm@20474
|
142 |
\item @{ML Variable.focus}~@{text B} decomposes the outermost @{text
|
wenzelm@20474
|
143 |
"\<And>"} prefix of proposition @{text "B"}.
|
wenzelm@20026
|
144 |
|
wenzelm@20026
|
145 |
\end{description}
|
wenzelm@20026
|
146 |
*}
|
wenzelm@20026
|
147 |
|
wenzelm@34999
|
148 |
text %mlex {* The following example (in theory @{theory Pure}) shows
|
wenzelm@34999
|
149 |
how to work with fixed term and type parameters work with
|
wenzelm@34999
|
150 |
type-inference.
|
wenzelm@34999
|
151 |
*}
|
wenzelm@34999
|
152 |
|
wenzelm@34999
|
153 |
typedecl foo -- {* some basic type for testing purposes *}
|
wenzelm@34999
|
154 |
|
wenzelm@34999
|
155 |
ML {*
|
wenzelm@34999
|
156 |
(*static compile-time context -- for testing only*)
|
wenzelm@34999
|
157 |
val ctxt0 = @{context};
|
wenzelm@34999
|
158 |
|
wenzelm@34999
|
159 |
(*locally fixed parameters -- no type assignment yet*)
|
wenzelm@34999
|
160 |
val ([x, y], ctxt1) = ctxt0 |> Variable.add_fixes ["x", "y"];
|
wenzelm@34999
|
161 |
|
wenzelm@34999
|
162 |
(*t1: most general fixed type; t1': most general arbitrary type*)
|
wenzelm@34999
|
163 |
val t1 = Syntax.read_term ctxt1 "x";
|
wenzelm@34999
|
164 |
val t1' = singleton (Variable.polymorphic ctxt1) t1;
|
wenzelm@34999
|
165 |
|
wenzelm@34999
|
166 |
(*term u enforces specific type assignment*)
|
wenzelm@34999
|
167 |
val u = Syntax.read_term ctxt1 "(x::foo) \<equiv> y";
|
wenzelm@34999
|
168 |
|
wenzelm@34999
|
169 |
(*official declaration of u -- propagates constraints etc.*)
|
wenzelm@34999
|
170 |
val ctxt2 = ctxt1 |> Variable.declare_term u;
|
wenzelm@34999
|
171 |
val t2 = Syntax.read_term ctxt2 "x"; (*x::foo is enforced*)
|
wenzelm@34999
|
172 |
*}
|
wenzelm@34999
|
173 |
|
wenzelm@34999
|
174 |
text {* In the above example, the starting context had been derived
|
wenzelm@34999
|
175 |
from the toplevel theory, which means that fixed variables are
|
wenzelm@34999
|
176 |
internalized literally: @{verbatim "x"} is mapped again to
|
wenzelm@34999
|
177 |
@{verbatim "x"}, and attempting to fix it again in the subsequent
|
wenzelm@34999
|
178 |
context is an error. Alternatively, fixed parameters can be renamed
|
wenzelm@34999
|
179 |
explicitly as follows:
|
wenzelm@34999
|
180 |
*}
|
wenzelm@34999
|
181 |
|
wenzelm@34999
|
182 |
ML {*
|
wenzelm@34999
|
183 |
val ctxt0 = @{context};
|
wenzelm@34999
|
184 |
val ([x1, x2, x3], ctxt1) =
|
wenzelm@34999
|
185 |
ctxt0 |> Variable.variant_fixes ["x", "x", "x"];
|
wenzelm@34999
|
186 |
*}
|
wenzelm@34999
|
187 |
|
wenzelm@34999
|
188 |
text {* \noindent Subsequent ML code can now work with the invented
|
wenzelm@34999
|
189 |
names of @{verbatim x1}, @{verbatim x2}, @{verbatim x3}, without
|
wenzelm@34999
|
190 |
depending on the details on the system policy for introducing these
|
wenzelm@34999
|
191 |
variants. Recall that within a proof body the system always invents
|
wenzelm@34999
|
192 |
fresh ``skolem constants'', e.g.\ as follows:
|
wenzelm@34999
|
193 |
*}
|
wenzelm@34999
|
194 |
|
wenzelm@34999
|
195 |
lemma "PROP XXX"
|
wenzelm@34999
|
196 |
proof -
|
wenzelm@34999
|
197 |
ML_prf %"ML" {*
|
wenzelm@34999
|
198 |
val ctxt0 = @{context};
|
wenzelm@34999
|
199 |
|
wenzelm@34999
|
200 |
val ([x1], ctxt1) = ctxt0 |> Variable.add_fixes ["x"];
|
wenzelm@34999
|
201 |
val ([x2], ctxt2) = ctxt1 |> Variable.add_fixes ["x"];
|
wenzelm@34999
|
202 |
val ([x3], ctxt3) = ctxt2 |> Variable.add_fixes ["x"];
|
wenzelm@34999
|
203 |
|
wenzelm@34999
|
204 |
val ([y1, y2], ctxt4) =
|
wenzelm@34999
|
205 |
ctxt3 |> Variable.variant_fixes ["y", "y"];
|
wenzelm@34999
|
206 |
*}
|
wenzelm@34999
|
207 |
oops
|
wenzelm@34999
|
208 |
|
wenzelm@34999
|
209 |
text {* \noindent In this situation @{ML Variable.add_fixes} and @{ML
|
wenzelm@34999
|
210 |
Variable.variant_fixes} are very similar, but identical name
|
wenzelm@34999
|
211 |
proposals given in a row are only accepted by the second version.
|
wenzelm@34999
|
212 |
*}
|
wenzelm@34999
|
213 |
|
wenzelm@18537
|
214 |
|
wenzelm@20474
|
215 |
section {* Assumptions \label{sec:assumptions} *}
|
wenzelm@20451
|
216 |
|
wenzelm@20458
|
217 |
text {*
|
wenzelm@20458
|
218 |
An \emph{assumption} is a proposition that it is postulated in the
|
wenzelm@20458
|
219 |
current context. Local conclusions may use assumptions as
|
wenzelm@20458
|
220 |
additional facts, but this imposes implicit hypotheses that weaken
|
wenzelm@20458
|
221 |
the overall statement.
|
wenzelm@20458
|
222 |
|
wenzelm@20474
|
223 |
Assumptions are restricted to fixed non-schematic statements, i.e.\
|
wenzelm@20474
|
224 |
all generality needs to be expressed by explicit quantifiers.
|
wenzelm@20458
|
225 |
Nevertheless, the result will be in HHF normal form with outermost
|
wenzelm@20458
|
226 |
quantifiers stripped. For example, by assuming @{text "\<And>x :: \<alpha>. P
|
wenzelm@20474
|
227 |
x"} we get @{text "\<And>x :: \<alpha>. P x \<turnstile> P ?x"} for schematic @{text "?x"}
|
wenzelm@20474
|
228 |
of fixed type @{text "\<alpha>"}. Local derivations accumulate more and
|
wenzelm@20474
|
229 |
more explicit references to hypotheses: @{text "A\<^isub>1, \<dots>,
|
wenzelm@20458
|
230 |
A\<^isub>n \<turnstile> B"} where @{text "A\<^isub>1, \<dots>, A\<^isub>n"} needs to
|
wenzelm@20458
|
231 |
be covered by the assumptions of the current context.
|
wenzelm@20458
|
232 |
|
wenzelm@20459
|
233 |
\medskip The @{text "add_assms"} operation augments the context by
|
wenzelm@20459
|
234 |
local assumptions, which are parameterized by an arbitrary @{text
|
wenzelm@20459
|
235 |
"export"} rule (see below).
|
wenzelm@20458
|
236 |
|
wenzelm@20458
|
237 |
The @{text "export"} operation moves facts from a (larger) inner
|
wenzelm@20458
|
238 |
context into a (smaller) outer context, by discharging the
|
wenzelm@20458
|
239 |
difference of the assumptions as specified by the associated export
|
wenzelm@20458
|
240 |
rules. Note that the discharged portion is determined by the
|
wenzelm@34997
|
241 |
difference of contexts, not the facts being exported! There is a
|
wenzelm@20459
|
242 |
separate flag to indicate a goal context, where the result is meant
|
wenzelm@30086
|
243 |
to refine an enclosing sub-goal of a structured proof state.
|
wenzelm@20458
|
244 |
|
wenzelm@20458
|
245 |
\medskip The most basic export rule discharges assumptions directly
|
wenzelm@20458
|
246 |
by means of the @{text "\<Longrightarrow>"} introduction rule:
|
wenzelm@20458
|
247 |
\[
|
wenzelm@34997
|
248 |
\infer[(@{text "\<Longrightarrow>\<dash>intro"})]{@{text "\<Gamma> - A \<turnstile> A \<Longrightarrow> B"}}{@{text "\<Gamma> \<turnstile> B"}}
|
wenzelm@20458
|
249 |
\]
|
wenzelm@20458
|
250 |
|
wenzelm@20458
|
251 |
The variant for goal refinements marks the newly introduced
|
wenzelm@20474
|
252 |
premises, which causes the canonical Isar goal refinement scheme to
|
wenzelm@20458
|
253 |
enforce unification with local premises within the goal:
|
wenzelm@20458
|
254 |
\[
|
wenzelm@34997
|
255 |
\infer[(@{text "#\<Longrightarrow>\<dash>intro"})]{@{text "\<Gamma> - A \<turnstile> #A \<Longrightarrow> B"}}{@{text "\<Gamma> \<turnstile> B"}}
|
wenzelm@20458
|
256 |
\]
|
wenzelm@20458
|
257 |
|
wenzelm@20474
|
258 |
\medskip Alternative versions of assumptions may perform arbitrary
|
wenzelm@20474
|
259 |
transformations on export, as long as the corresponding portion of
|
wenzelm@20459
|
260 |
hypotheses is removed from the given facts. For example, a local
|
wenzelm@20459
|
261 |
definition works by fixing @{text "x"} and assuming @{text "x \<equiv> t"},
|
wenzelm@20459
|
262 |
with the following export rule to reverse the effect:
|
wenzelm@20458
|
263 |
\[
|
wenzelm@34997
|
264 |
\infer[(@{text "\<equiv>\<dash>expand"})]{@{text "\<Gamma> - (x \<equiv> t) \<turnstile> B t"}}{@{text "\<Gamma> \<turnstile> B x"}}
|
wenzelm@20458
|
265 |
\]
|
wenzelm@20474
|
266 |
This works, because the assumption @{text "x \<equiv> t"} was introduced in
|
wenzelm@20474
|
267 |
a context with @{text "x"} being fresh, so @{text "x"} does not
|
wenzelm@20474
|
268 |
occur in @{text "\<Gamma>"} here.
|
wenzelm@20458
|
269 |
*}
|
wenzelm@20458
|
270 |
|
wenzelm@20458
|
271 |
text %mlref {*
|
wenzelm@20458
|
272 |
\begin{mldecls}
|
wenzelm@20458
|
273 |
@{index_ML_type Assumption.export} \\
|
wenzelm@20458
|
274 |
@{index_ML Assumption.assume: "cterm -> thm"} \\
|
wenzelm@20458
|
275 |
@{index_ML Assumption.add_assms:
|
wenzelm@20459
|
276 |
"Assumption.export ->
|
wenzelm@20459
|
277 |
cterm list -> Proof.context -> thm list * Proof.context"} \\
|
wenzelm@20459
|
278 |
@{index_ML Assumption.add_assumes: "
|
wenzelm@20459
|
279 |
cterm list -> Proof.context -> thm list * Proof.context"} \\
|
wenzelm@20458
|
280 |
@{index_ML Assumption.export: "bool -> Proof.context -> Proof.context -> thm -> thm"} \\
|
wenzelm@20458
|
281 |
\end{mldecls}
|
wenzelm@20458
|
282 |
|
wenzelm@20458
|
283 |
\begin{description}
|
wenzelm@20458
|
284 |
|
wenzelm@20459
|
285 |
\item @{ML_type Assumption.export} represents arbitrary export
|
wenzelm@20459
|
286 |
rules, which is any function of type @{ML_type "bool -> cterm list -> thm -> thm"},
|
wenzelm@20459
|
287 |
where the @{ML_type "bool"} indicates goal mode, and the @{ML_type
|
wenzelm@20459
|
288 |
"cterm list"} the collection of assumptions to be discharged
|
wenzelm@20459
|
289 |
simultaneously.
|
wenzelm@20458
|
290 |
|
wenzelm@20459
|
291 |
\item @{ML Assumption.assume}~@{text "A"} turns proposition @{text
|
wenzelm@34997
|
292 |
"A"} into a primitive assumption @{text "A \<turnstile> A'"}, where the
|
wenzelm@34997
|
293 |
conclusion @{text "A'"} is in HHF normal form.
|
wenzelm@20458
|
294 |
|
wenzelm@20474
|
295 |
\item @{ML Assumption.add_assms}~@{text "r As"} augments the context
|
wenzelm@20474
|
296 |
by assumptions @{text "As"} with export rule @{text "r"}. The
|
wenzelm@20474
|
297 |
resulting facts are hypothetical theorems as produced by the raw
|
wenzelm@20474
|
298 |
@{ML Assumption.assume}.
|
wenzelm@20459
|
299 |
|
wenzelm@20459
|
300 |
\item @{ML Assumption.add_assumes}~@{text "As"} is a special case of
|
wenzelm@20459
|
301 |
@{ML Assumption.add_assms} where the export rule performs @{text
|
wenzelm@34997
|
302 |
"\<Longrightarrow>\<dash>intro"} or @{text "#\<Longrightarrow>\<dash>intro"}, depending on goal
|
wenzelm@34997
|
303 |
mode.
|
wenzelm@20458
|
304 |
|
wenzelm@20474
|
305 |
\item @{ML Assumption.export}~@{text "is_goal inner outer thm"}
|
wenzelm@20474
|
306 |
exports result @{text "thm"} from the the @{text "inner"} context
|
wenzelm@20459
|
307 |
back into the @{text "outer"} one; @{text "is_goal = true"} means
|
wenzelm@20459
|
308 |
this is a goal context. The result is in HHF normal form. Note
|
wenzelm@20459
|
309 |
that @{ML "ProofContext.export"} combines @{ML "Variable.export"}
|
wenzelm@20459
|
310 |
and @{ML "Assumption.export"} in the canonical way.
|
wenzelm@20458
|
311 |
|
wenzelm@20458
|
312 |
\end{description}
|
wenzelm@20458
|
313 |
*}
|
wenzelm@20451
|
314 |
|
wenzelm@34999
|
315 |
text %mlex {* The following example demonstrates how rules can be
|
wenzelm@34999
|
316 |
derived by building up a context of assumptions first, and exporting
|
wenzelm@34999
|
317 |
some local fact afterwards. We refer to @{theory Pure} equality
|
wenzelm@34999
|
318 |
here for testing purposes.
|
wenzelm@34999
|
319 |
*}
|
wenzelm@34999
|
320 |
|
wenzelm@34999
|
321 |
ML {*
|
wenzelm@34999
|
322 |
(*static compile-time context -- for testing only*)
|
wenzelm@34999
|
323 |
val ctxt0 = @{context};
|
wenzelm@34999
|
324 |
|
wenzelm@34999
|
325 |
val ([eq], ctxt1) =
|
wenzelm@34999
|
326 |
ctxt0 |> Assumption.add_assumes [@{cprop "x \<equiv> y"}];
|
wenzelm@34999
|
327 |
val eq' = Thm.symmetric eq;
|
wenzelm@34999
|
328 |
|
wenzelm@34999
|
329 |
(*back to original context -- discharges assumption*)
|
wenzelm@34999
|
330 |
val r = Assumption.export false ctxt1 ctxt0 eq';
|
wenzelm@34999
|
331 |
*}
|
wenzelm@34999
|
332 |
|
wenzelm@34999
|
333 |
text {* \noindent Note that the variables of the resulting rule are
|
wenzelm@34999
|
334 |
not generalized. This would have required to fix them properly in
|
wenzelm@34999
|
335 |
the context beforehand, and export wrt.\ variables afterwards (cf.\
|
wenzelm@34999
|
336 |
@{ML Variable.export} or the combined @{ML "ProofContext.export"}).
|
wenzelm@34999
|
337 |
*}
|
wenzelm@34999
|
338 |
|
wenzelm@20451
|
339 |
|
wenzelm@34997
|
340 |
section {* Structured goals and results \label{sec:struct-goals} *}
|
wenzelm@20451
|
341 |
|
wenzelm@20472
|
342 |
text {*
|
wenzelm@20472
|
343 |
Local results are established by monotonic reasoning from facts
|
wenzelm@20474
|
344 |
within a context. This allows common combinations of theorems,
|
wenzelm@20474
|
345 |
e.g.\ via @{text "\<And>/\<Longrightarrow>"} elimination, resolution rules, or equational
|
wenzelm@20474
|
346 |
reasoning, see \secref{sec:thms}. Unaccounted context manipulations
|
wenzelm@20474
|
347 |
should be avoided, notably raw @{text "\<And>/\<Longrightarrow>"} introduction or ad-hoc
|
wenzelm@20472
|
348 |
references to free variables or assumptions not present in the proof
|
wenzelm@20472
|
349 |
context.
|
wenzelm@20451
|
350 |
|
wenzelm@20491
|
351 |
\medskip The @{text "SUBPROOF"} combinator allows to structure a
|
wenzelm@20491
|
352 |
tactical proof recursively by decomposing a selected sub-goal:
|
wenzelm@20491
|
353 |
@{text "(\<And>x. A(x) \<Longrightarrow> B(x)) \<Longrightarrow> \<dots>"} is turned into @{text "B(x) \<Longrightarrow> \<dots>"}
|
wenzelm@20491
|
354 |
after fixing @{text "x"} and assuming @{text "A(x)"}. This means
|
wenzelm@20491
|
355 |
the tactic needs to solve the conclusion, but may use the premise as
|
wenzelm@20491
|
356 |
a local fact, for locally fixed variables.
|
wenzelm@20451
|
357 |
|
wenzelm@34997
|
358 |
The family of @{text "FOCUS"} combinators is similar to @{text
|
wenzelm@34997
|
359 |
"SUBPROOF"}, but allows to retain schematic variables and pending
|
wenzelm@34997
|
360 |
subgoals in the resulting goal state.
|
wenzelm@34997
|
361 |
|
wenzelm@20491
|
362 |
The @{text "prove"} operation provides an interface for structured
|
wenzelm@20491
|
363 |
backwards reasoning under program control, with some explicit sanity
|
wenzelm@20491
|
364 |
checks of the result. The goal context can be augmented by
|
wenzelm@20491
|
365 |
additional fixed variables (cf.\ \secref{sec:variables}) and
|
wenzelm@20491
|
366 |
assumptions (cf.\ \secref{sec:assumptions}), which will be available
|
wenzelm@20491
|
367 |
as local facts during the proof and discharged into implications in
|
wenzelm@20491
|
368 |
the result. Type and term variables are generalized as usual,
|
wenzelm@20491
|
369 |
according to the context.
|
wenzelm@18537
|
370 |
|
wenzelm@20491
|
371 |
The @{text "obtain"} operation produces results by eliminating
|
wenzelm@20491
|
372 |
existing facts by means of a given tactic. This acts like a dual
|
wenzelm@20491
|
373 |
conclusion: the proof demonstrates that the context may be augmented
|
wenzelm@34997
|
374 |
by parameters and assumptions, without affecting any conclusions
|
wenzelm@34997
|
375 |
that do not mention these parameters. See also
|
wenzelm@20491
|
376 |
\cite{isabelle-isar-ref} for the user-level @{text "\<OBTAIN>"} and
|
wenzelm@20491
|
377 |
@{text "\<GUESS>"} elements. Final results, which may not refer to
|
wenzelm@20491
|
378 |
the parameters in the conclusion, need to exported explicitly into
|
wenzelm@20491
|
379 |
the original context.
|
wenzelm@18537
|
380 |
*}
|
wenzelm@18537
|
381 |
|
wenzelm@20472
|
382 |
text %mlref {*
|
wenzelm@20472
|
383 |
\begin{mldecls}
|
wenzelm@32207
|
384 |
@{index_ML SUBPROOF: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\
|
wenzelm@34997
|
385 |
@{index_ML Subgoal.FOCUS: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\
|
wenzelm@34997
|
386 |
@{index_ML Subgoal.FOCUS_PREMS: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\
|
wenzelm@34997
|
387 |
@{index_ML Subgoal.FOCUS_PARAMS: "(Subgoal.focus -> tactic) -> Proof.context -> int -> tactic"} \\
|
wenzelm@20547
|
388 |
\end{mldecls}
|
wenzelm@34997
|
389 |
|
wenzelm@20547
|
390 |
\begin{mldecls}
|
wenzelm@20472
|
391 |
@{index_ML Goal.prove: "Proof.context -> string list -> term list -> term ->
|
wenzelm@20472
|
392 |
({prems: thm list, context: Proof.context} -> tactic) -> thm"} \\
|
wenzelm@20472
|
393 |
@{index_ML Goal.prove_multi: "Proof.context -> string list -> term list -> term list ->
|
wenzelm@20472
|
394 |
({prems: thm list, context: Proof.context} -> tactic) -> thm list"} \\
|
wenzelm@20547
|
395 |
\end{mldecls}
|
wenzelm@20547
|
396 |
\begin{mldecls}
|
wenzelm@20491
|
397 |
@{index_ML Obtain.result: "(Proof.context -> tactic) ->
|
wenzelm@32207
|
398 |
thm list -> Proof.context -> ((string * cterm) list * thm list) * Proof.context"} \\
|
wenzelm@20472
|
399 |
\end{mldecls}
|
wenzelm@18537
|
400 |
|
wenzelm@20472
|
401 |
\begin{description}
|
wenzelm@18537
|
402 |
|
wenzelm@30087
|
403 |
\item @{ML SUBPROOF}~@{text "tac ctxt i"} decomposes the structure
|
wenzelm@30087
|
404 |
of the specified sub-goal, producing an extended context and a
|
wenzelm@30087
|
405 |
reduced goal, which needs to be solved by the given tactic. All
|
wenzelm@30087
|
406 |
schematic parameters of the goal are imported into the context as
|
wenzelm@30087
|
407 |
fixed ones, which may not be instantiated in the sub-proof.
|
wenzelm@20491
|
408 |
|
wenzelm@34997
|
409 |
\item @{ML Subgoal.FOCUS}, @{ML Subgoal.FOCUS_PREMS}, and @{ML
|
wenzelm@34997
|
410 |
Subgoal.FOCUS_PARAMS} are similar to @{ML SUBPROOF}, but are
|
wenzelm@34997
|
411 |
slightly more flexible: only the specified parts of the subgoal are
|
wenzelm@34997
|
412 |
imported into the context, and the body tactic may introduce new
|
wenzelm@34997
|
413 |
subgoals and schematic variables.
|
wenzelm@34997
|
414 |
|
wenzelm@20472
|
415 |
\item @{ML Goal.prove}~@{text "ctxt xs As C tac"} states goal @{text
|
wenzelm@20474
|
416 |
"C"} in the context augmented by fixed variables @{text "xs"} and
|
wenzelm@20474
|
417 |
assumptions @{text "As"}, and applies tactic @{text "tac"} to solve
|
wenzelm@20474
|
418 |
it. The latter may depend on the local assumptions being presented
|
wenzelm@20474
|
419 |
as facts. The result is in HHF normal form.
|
wenzelm@18537
|
420 |
|
wenzelm@20472
|
421 |
\item @{ML Goal.prove_multi} is simular to @{ML Goal.prove}, but
|
wenzelm@20491
|
422 |
states several conclusions simultaneously. The goal is encoded by
|
wenzelm@21827
|
423 |
means of Pure conjunction; @{ML Goal.conjunction_tac} will turn this
|
wenzelm@21827
|
424 |
into a collection of individual subgoals.
|
wenzelm@20472
|
425 |
|
wenzelm@20491
|
426 |
\item @{ML Obtain.result}~@{text "tac thms ctxt"} eliminates the
|
wenzelm@20491
|
427 |
given facts using a tactic, which results in additional fixed
|
wenzelm@20491
|
428 |
variables and assumptions in the context. Final results need to be
|
wenzelm@20491
|
429 |
exported explicitly.
|
wenzelm@20472
|
430 |
|
wenzelm@20472
|
431 |
\end{description}
|
wenzelm@20472
|
432 |
*}
|
wenzelm@30273
|
433 |
|
wenzelm@18537
|
434 |
end
|