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