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