| author | wenzelm | 
| Sun, 24 Aug 2025 20:26:02 +0200 | |
| changeset 83053 | c1ccd17fb70f | 
| parent 78087 | 90b64ffc48a3 | 
| 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}
 | 
| 73764 | 95 |   @{define_ML Variable.add_fixes: "
 | 
| 20474 | 96 | string list -> Proof.context -> string list * Proof.context"} \\ | 
| 73764 | 97 |   @{define_ML Variable.variant_fixes: "
 | 
| 20474 | 98 | string list -> Proof.context -> string list * Proof.context"} \\ | 
| 73764 | 99 |   @{define_ML Variable.declare_term: "term -> Proof.context -> Proof.context"} \\
 | 
| 100 |   @{define_ML Variable.declare_constraints: "term -> Proof.context -> Proof.context"} \\
 | |
| 101 |   @{define_ML Variable.export: "Proof.context -> Proof.context -> thm list -> thm list"} \\
 | |
| 102 |   @{define_ML Variable.polymorphic: "Proof.context -> term list -> term list"} \\
 | |
| 103 |   @{define_ML Variable.import: "bool -> thm list -> Proof.context ->
 | |
| 74266 | 104 | ((ctyp TVars.table * cterm Vars.table) * thm list) | 
| 66663 | 105 | * Proof.context"} \\ | 
| 73764 | 106 |   @{define_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}
 | 
| 73764 | 266 |   @{define_ML_type Assumption.export} \\
 | 
| 267 |   @{define_ML Assumption.assume: "Proof.context -> cterm -> thm"} \\
 | |
| 268 |   @{define_ML Assumption.add_assms:
 | |
| 20459 | 269 | "Assumption.export -> | 
| 270 | cterm list -> Proof.context -> thm list * Proof.context"} \\ | |
| 73764 | 271 |   @{define_ML Assumption.add_assumes: "
 | 
| 20459 | 272 | cterm list -> Proof.context -> thm list * Proof.context"} \\ | 
| 78086 | 273 |   @{define_ML Assumption.export: "Proof.context -> Proof.context -> thm -> thm"} \\
 | 
| 78087 | 274 |   @{define_ML Assumption.export_goal: "Proof.context -> Proof.context -> thm -> thm"} \\
 | 
| 74994 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 275 |   @{define_ML Assumption.export_term: "Proof.context -> Proof.context -> term -> term"} \\
 | 
| 20458 | 276 |   \end{mldecls}
 | 
| 277 | ||
| 74994 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 278 | \<^descr> Type \<^ML_type>\<open>Assumption.export\<close> represents export rules, as a pair of | 
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 279 | functions \<^ML_type>\<open>bool -> cterm list -> (thm -> thm) * (term -> term)\<close>. | 
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 280 | The \<^ML_type>\<open>bool\<close> argument indicates goal mode, and the \<^ML_type>\<open>cterm list\<close> | 
| 61854 | 281 | the collection of assumptions to be discharged simultaneously. | 
| 20458 | 282 | |
| 69597 | 283 | \<^descr> \<^ML>\<open>Assumption.assume\<close>~\<open>ctxt A\<close> turns proposition \<open>A\<close> into a primitive | 
| 61854 | 284 | assumption \<open>A \<turnstile> A'\<close>, where the conclusion \<open>A'\<close> is in HHF normal form. | 
| 20458 | 285 | |
| 69597 | 286 | \<^descr> \<^ML>\<open>Assumption.add_assms\<close>~\<open>r As\<close> augments the context by assumptions \<open>As\<close> | 
| 61854 | 287 | with export rule \<open>r\<close>. The resulting facts are hypothetical theorems as | 
| 69597 | 288 | produced by the raw \<^ML>\<open>Assumption.assume\<close>. | 
| 20459 | 289 | |
| 74994 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 290 | \<^descr> \<^ML>\<open>Assumption.add_assumes\<close>~\<open>As\<close> is a special case of | 
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 291 | \<^ML>\<open>Assumption.add_assms\<close> where the export rule performs \<open>\<Longrightarrow>\<hyphen>intro\<close> or | 
| 61854 | 292 | \<open>#\<Longrightarrow>\<hyphen>intro\<close>, depending on goal mode. | 
| 20458 | 293 | |
| 78086 | 294 | \<^descr> \<^ML>\<open>Assumption.export\<close>~\<open>inner outer thm\<close> exports result \<open>thm\<close> from the | 
| 295 | \<open>inner\<close> context back into the \<open>outer\<close> one; \<^ML>\<open>Assumption.export_goal\<close> | |
| 78087 | 296 | does the same in a goal context (\<^theory_text>\<open>fix/assume/show\<close> in Isabelle/Isar). The | 
| 297 | result is always in HHF normal form. Note that \<^ML>\<open>Proof_Context.export\<close> | |
| 298 | combines \<^ML>\<open>Variable.export\<close> and \<^ML>\<open>Assumption.export\<close> in the | |
| 299 | canonical way. | |
| 74994 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 300 | |
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 301 | \<^descr> \<^ML>\<open>Assumption.export_term\<close>~\<open>inner outer t\<close> exports term \<open>t\<close> from the | 
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 302 | \<open>inner\<close> context back into the \<open>outer\<close> one. This is analogous to | 
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 303 | \<^ML>\<open>Assumption.export\<close>, but only takes syntactical aspects of the | 
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 304 | context into account (such as locally specified variables as seen in | 
| 
26794ec7c78e
some updates and clarification on Assumption.export_term;
 wenzelm parents: 
74365diff
changeset | 305 |   @{command define} or @{command obtain}).
 | 
| 58618 | 306 | \<close> | 
| 20451 | 307 | |
| 61854 | 308 | text %mlex \<open> | 
| 309 | The following example demonstrates how rules can be derived by building up a | |
| 310 | context of assumptions first, and exporting some local fact afterwards. We | |
| 69597 | 311 | refer to \<^theory>\<open>Pure\<close> equality here for testing purposes. | 
| 58618 | 312 | \<close> | 
| 34932 | 313 | |
| 59902 | 314 | ML_val \<open> | 
| 34932 | 315 | (*static compile-time context -- for testing only*) | 
| 69597 | 316 | val ctxt0 = \<^context>; | 
| 34932 | 317 | |
| 318 | val ([eq], ctxt1) = | |
| 69597 | 319 | ctxt0 |> Assumption.add_assumes [\<^cprop>\<open>x \<equiv> y\<close>]; | 
| 34932 | 320 | val eq' = Thm.symmetric eq; | 
| 321 | ||
| 322 | (*back to original context -- discharges assumption*) | |
| 78086 | 323 | val r = Assumption.export ctxt1 ctxt0 eq'; | 
| 58618 | 324 | \<close> | 
| 34932 | 325 | |
| 61854 | 326 | text \<open> | 
| 327 | Note that the variables of the resulting rule are not generalized. This | |
| 328 | would have required to fix them properly in the context beforehand, and | |
| 69597 | 329 | export wrt.\ variables afterwards (cf.\ \<^ML>\<open>Variable.export\<close> or the | 
| 330 | combined \<^ML>\<open>Proof_Context.export\<close>). | |
| 61854 | 331 | \<close> | 
| 34932 | 332 | |
| 20451 | 333 | |
| 58618 | 334 | section \<open>Structured goals and results \label{sec:struct-goals}\<close>
 | 
| 20451 | 335 | |
| 58618 | 336 | text \<open> | 
| 61854 | 337 | Local results are established by monotonic reasoning from facts within a | 
| 338 | context. This allows common combinations of theorems, e.g.\ via \<open>\<And>/\<Longrightarrow>\<close> | |
| 339 | elimination, resolution rules, or equational reasoning, see | |
| 340 |   \secref{sec:thms}. Unaccounted context manipulations should be avoided,
 | |
| 341 | notably raw \<open>\<And>/\<Longrightarrow>\<close> introduction or ad-hoc references to free variables or | |
| 342 | assumptions not present in the proof context. | |
| 18537 | 343 | |
| 61416 | 344 | \<^medskip> | 
| 61854 | 345 | The \<open>SUBPROOF\<close> combinator allows to structure a tactical proof recursively | 
| 346 | by decomposing a selected sub-goal: \<open>(\<And>x. A(x) \<Longrightarrow> B(x)) \<Longrightarrow> \<dots>\<close> is turned into | |
| 347 | \<open>B(x) \<Longrightarrow> \<dots>\<close> after fixing \<open>x\<close> and assuming \<open>A(x)\<close>. This means the tactic needs | |
| 348 | to solve the conclusion, but may use the premise as a local fact, for | |
| 349 | locally fixed variables. | |
| 18537 | 350 | |
| 61854 | 351 | The family of \<open>FOCUS\<close> combinators is similar to \<open>SUBPROOF\<close>, but allows to | 
| 352 | retain schematic variables and pending subgoals in the resulting goal state. | |
| 34930 | 353 | |
| 61854 | 354 | The \<open>prove\<close> operation provides an interface for structured backwards | 
| 355 | reasoning under program control, with some explicit sanity checks of the | |
| 356 | result. The goal context can be augmented by additional fixed variables | |
| 357 |   (cf.\ \secref{sec:variables}) and assumptions (cf.\
 | |
| 358 |   \secref{sec:assumptions}), which will be available as local facts during the
 | |
| 359 | proof and discharged into implications in the result. Type and term | |
| 360 | variables are generalized as usual, according to the context. | |
| 18537 | 361 | |
| 61854 | 362 | The \<open>obtain\<close> operation produces results by eliminating existing facts by | 
| 363 | means of a given tactic. This acts like a dual conclusion: the proof | |
| 364 | demonstrates that the context may be augmented by parameters and | |
| 365 | assumptions, without affecting any conclusions that do not mention these | |
| 76987 | 366 | parameters. See also \<^cite>\<open>"isabelle-isar-ref"\<close> for the corresponding Isar | 
| 74365 
b49bd5d9041f
improper proof command 'guess' moved to separate theory "Pure-ex.Guess";
 wenzelm parents: 
74266diff
changeset | 367 |   proof command @{command obtain}. Final results, which may not refer to the
 | 
| 
b49bd5d9041f
improper proof command 'guess' moved to separate theory "Pure-ex.Guess";
 wenzelm parents: 
74266diff
changeset | 368 | parameters in the conclusion, need to exported explicitly into the original | 
| 
b49bd5d9041f
improper proof command 'guess' moved to separate theory "Pure-ex.Guess";
 wenzelm parents: 
74266diff
changeset | 369 | context. | 
| 
b49bd5d9041f
improper proof command 'guess' moved to separate theory "Pure-ex.Guess";
 wenzelm parents: 
74266diff
changeset | 370 | \<close> | 
| 18537 | 371 | |
| 58618 | 372 | text %mlref \<open> | 
| 20472 | 373 |   \begin{mldecls}
 | 
| 73764 | 374 |   @{define_ML SUBPROOF: "(Subgoal.focus -> tactic) ->
 | 
| 39821 | 375 | Proof.context -> int -> tactic"} \\ | 
| 73764 | 376 |   @{define_ML Subgoal.FOCUS: "(Subgoal.focus -> tactic) ->
 | 
| 39821 | 377 | Proof.context -> int -> tactic"} \\ | 
| 73764 | 378 |   @{define_ML Subgoal.FOCUS_PREMS: "(Subgoal.focus -> tactic) ->
 | 
| 39821 | 379 | Proof.context -> int -> tactic"} \\ | 
| 73764 | 380 |   @{define_ML Subgoal.FOCUS_PARAMS: "(Subgoal.focus -> tactic) ->
 | 
| 39821 | 381 | Proof.context -> int -> tactic"} \\ | 
| 73764 | 382 |   @{define_ML Subgoal.focus: "Proof.context -> int -> binding list option ->
 | 
| 60695 
757549b4bbe6
Variable.focus etc.: optional bindings provided by user;
 wenzelm parents: 
60642diff
changeset | 383 | thm -> Subgoal.focus * thm"} \\ | 
| 73764 | 384 |   @{define_ML Subgoal.focus_prems: "Proof.context -> int -> binding list option ->
 | 
| 60695 
757549b4bbe6
Variable.focus etc.: optional bindings provided by user;
 wenzelm parents: 
60642diff
changeset | 385 | thm -> Subgoal.focus * thm"} \\ | 
| 73764 | 386 |   @{define_ML Subgoal.focus_params: "Proof.context -> int -> binding list option ->
 | 
| 60695 
757549b4bbe6
Variable.focus etc.: optional bindings provided by user;
 wenzelm parents: 
60642diff
changeset | 387 | thm -> Subgoal.focus * thm"} \\ | 
| 20547 | 388 |   \end{mldecls}
 | 
| 34930 | 389 | |
| 20547 | 390 |   \begin{mldecls}
 | 
| 73764 | 391 |   @{define_ML Goal.prove: "Proof.context -> string list -> term list -> term ->
 | 
| 20472 | 392 |   ({prems: thm list, context: Proof.context} -> tactic) -> thm"} \\
 | 
| 73764 | 393 |   @{define_ML Goal.prove_common: "Proof.context -> int option ->
 | 
| 59564 
fdc03c8daacc
Goal.prove_multi is superseded by the fully general Goal.prove_common;
 wenzelm parents: 
58801diff
changeset | 394 | string list -> term list -> term list -> | 
| 20472 | 395 |   ({prems: thm list, context: Proof.context} -> tactic) -> thm list"} \\
 | 
| 20547 | 396 |   \end{mldecls}
 | 
| 397 |   \begin{mldecls}
 | |
| 73764 | 398 |   @{define_ML Obtain.result: "(Proof.context -> tactic) -> thm list ->
 | 
| 39821 | 399 | Proof.context -> ((string * cterm) list * thm list) * Proof.context"} \\ | 
| 20472 | 400 |   \end{mldecls}
 | 
| 18537 | 401 | |
| 69597 | 402 | \<^descr> \<^ML>\<open>SUBPROOF\<close>~\<open>tac ctxt i\<close> decomposes the structure of the specified | 
| 61854 | 403 | sub-goal, producing an extended context and a reduced goal, which needs to | 
| 404 | be solved by the given tactic. All schematic parameters of the goal are | |
| 405 | imported into the context as fixed ones, which may not be instantiated in | |
| 406 | the sub-proof. | |
| 20491 | 407 | |
| 69597 | 408 | \<^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 | 409 | flexible: only the specified parts of the subgoal are imported into the | 
| 410 | context, and the body tactic may introduce new subgoals and schematic | |
| 411 | variables. | |
| 34930 | 412 | |
| 69597 | 413 | \<^descr> \<^ML>\<open>Subgoal.focus\<close>, \<^ML>\<open>Subgoal.focus_prems\<close>, \<^ML>\<open>Subgoal.focus_params\<close> | 
| 61854 | 414 | extract the focus information from a goal state in the same way as the | 
| 415 | corresponding tacticals above. This is occasionally useful to experiment | |
| 416 | without writing actual tactics yet. | |
| 39853 | 417 | |
| 69597 | 418 | \<^descr> \<^ML>\<open>Goal.prove\<close>~\<open>ctxt xs As C tac\<close> states goal \<open>C\<close> in the context | 
| 61854 | 419 | augmented by fixed variables \<open>xs\<close> and assumptions \<open>As\<close>, and applies tactic | 
| 420 | \<open>tac\<close> to solve it. The latter may depend on the local assumptions being | |
| 421 | presented as facts. The result is in HHF normal form. | |
| 18537 | 422 | |
| 69597 | 423 | \<^descr> \<^ML>\<open>Goal.prove_common\<close>~\<open>ctxt fork_pri\<close> is the common form to state and | 
| 424 | prove a simultaneous goal statement, where \<^ML>\<open>Goal.prove\<close> is a convenient | |
| 61854 | 425 | shorthand that is most frequently used in applications. | 
| 59564 
fdc03c8daacc
Goal.prove_multi is superseded by the fully general Goal.prove_common;
 wenzelm parents: 
58801diff
changeset | 426 | |
| 
fdc03c8daacc
Goal.prove_multi is superseded by the fully general Goal.prove_common;
 wenzelm parents: 
58801diff
changeset | 427 | The given list of simultaneous conclusions is encoded in the goal state by | 
| 69597 | 428 | means of Pure conjunction: \<^ML>\<open>Goal.conjunction_tac\<close> will turn this into a | 
| 61854 | 429 | 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: 
58801diff
changeset | 430 | state is usually required for advanced induction. | 
| 
fdc03c8daacc
Goal.prove_multi is superseded by the fully general Goal.prove_common;
 wenzelm parents: 
58801diff
changeset | 431 | |
| 61854 | 432 | It is possible to provide an optional priority for a forked proof, typically | 
| 69597 | 433 | \<^ML>\<open>SOME ~1\<close>, while \<^ML>\<open>NONE\<close> means the proof is immediate (sequential) | 
| 434 | as for \<^ML>\<open>Goal.prove\<close>. Note that a forked proof does not exhibit any | |
| 61854 | 435 | failures in the usual way via exceptions in ML, but accumulates error | 
| 436 | situations under the execution id of the running transaction. Thus the | |
| 437 | system is able to expose error messages ultimately to the end-user, even | |
| 438 | though the subsequent ML code misses them. | |
| 20472 | 439 | |
| 69597 | 440 | \<^descr> \<^ML>\<open>Obtain.result\<close>~\<open>tac thms ctxt\<close> eliminates the given facts using a | 
| 61854 | 441 | tactic, which results in additional fixed variables and assumptions in the | 
| 442 | context. Final results need to be exported explicitly. | |
| 58618 | 443 | \<close> | 
| 30272 | 444 | |
| 61854 | 445 | text %mlex \<open> | 
| 446 | The following minimal example illustrates how to access the focus | |
| 447 | information of a structured goal state. | |
| 448 | \<close> | |
| 39853 | 449 | |
| 40964 | 450 | notepad | 
| 451 | begin | |
| 39853 | 452 | fix A B C :: "'a \<Rightarrow> bool" | 
| 453 | ||
| 454 | have "\<And>x. A x \<Longrightarrow> B x \<Longrightarrow> C x" | |
| 455 | ML_val | |
| 58728 | 456 |      \<open>val {goal, context = goal_ctxt, ...} = @{Isar.goal};
 | 
| 39853 | 457 |       val (focus as {params, asms, concl, ...}, goal') =
 | 
| 69597 | 458 | Subgoal.focus goal_ctxt 1 (SOME [\<^binding>\<open>x\<close>]) goal; | 
| 39853 | 459 | val [A, B] = #prems focus; | 
| 58728 | 460 | val [(_, x)] = #params focus;\<close> | 
| 58801 | 461 | sorry | 
| 462 | end | |
| 39853 | 463 | |
| 61416 | 464 | text \<open> | 
| 465 | \<^medskip> | |
| 61854 | 466 | The next example demonstrates forward-elimination in a local context, using | 
| 69597 | 467 | \<^ML>\<open>Obtain.result\<close>. | 
| 61854 | 468 | \<close> | 
| 39851 | 469 | |
| 40964 | 470 | notepad | 
| 471 | begin | |
| 39851 | 472 | assume ex: "\<exists>x. B x" | 
| 473 | ||
| 58728 | 474 | ML_prf %"ML" | 
| 69597 | 475 | \<open>val ctxt0 = \<^context>; | 
| 39851 | 476 | val (([(_, x)], [B]), ctxt1) = ctxt0 | 
| 60754 | 477 |       |> Obtain.result (fn _ => eresolve_tac ctxt0 @{thms exE} 1) [@{thm ex}];\<close>
 | 
| 58728 | 478 | ML_prf %"ML" | 
| 479 |    \<open>singleton (Proof_Context.export ctxt1 ctxt0) @{thm refl};\<close>
 | |
| 480 | ML_prf %"ML" | |
| 481 | \<open>Proof_Context.export ctxt1 ctxt0 [Thm.reflexive x] | |
| 482 | handle ERROR msg => (warning msg; []);\<close> | |
| 40964 | 483 | end | 
| 39851 | 484 | |
| 18537 | 485 | end |