5 |
5 |
6 chapter {* First Steps *} |
6 chapter {* First Steps *} |
7 |
7 |
8 text {* |
8 text {* |
9 |
9 |
10 Isabelle programming is done in Standard ML. |
10 Isabelle programming is done in SML. Just like lemmas and proofs, SML-code |
11 Just like lemmas and proofs, SML-code in Isabelle is part of a |
11 in Isabelle is part of a theory. If you want to follow the code written in |
12 theory. If you want to follow the code written in this chapter, we |
12 this chapter, we assume you are working inside the theory defined by |
13 assume you are working inside the theory defined by |
|
14 |
13 |
15 \begin{center} |
14 \begin{center} |
16 \begin{tabular}{@ {}l} |
15 \begin{tabular}{@ {}l} |
17 \isacommand{theory} FirstSteps\\ |
16 \isacommand{theory} FirstSteps\\ |
18 \isacommand{imports} Main\\ |
17 \isacommand{imports} Main\\ |
62 |
61 |
63 section {* Debugging and Printing *} |
62 section {* Debugging and Printing *} |
64 |
63 |
65 text {* |
64 text {* |
66 |
65 |
67 During developments you might find it necessary to quickly inspect some data |
66 During development you might find it necessary to inspect some data |
68 in your code. This can be done in a ``quick-and-dirty'' fashion using |
67 in your code. This can be done in a ``quick-and-dirty'' fashion using |
69 the function @{ML "warning"}. For example |
68 the function @{ML "warning"}. For example |
70 |
69 |
71 @{ML [display] "warning \"any string\""} |
70 @{ML [display] "warning \"any string\""} |
72 |
71 |
73 will print out @{ML_text [quotes] "any string"} inside the response buffer of Isabelle. |
72 will print out @{ML_text [quotes] "any string"} inside the response buffer |
74 If you develop under PolyML, then there is a convenient, though again |
73 of Isabelle. This function expects a string. If you develop under PolyML, |
75 ``quick-and-dirty'', method for converting values into strings, |
74 then there is a convenient, though again ``quick-and-dirty'', method for |
76 for example: |
75 converting values into strings, for example: |
77 |
76 |
78 @{ML [display] "warning (makestring 1)"} |
77 @{ML [display] "warning (makestring 1)"} |
79 |
78 |
80 However this only works if the type of what is converted is monomorphic and is not |
79 However this only works if the type of what is converted is monomorphic and is not |
81 a function. |
80 a function. |
82 |
81 |
83 The funtion @{ML "warning"} should only be used for testing purposes, because any |
82 The funtion @{ML "warning"} should only be used for testing purposes, because any |
84 output this funtion generates will be overwritten as soon as an error is |
83 output this funtion generates will be overwritten as soon as an error is |
85 raised. Therefore for printing anything more serious and elaborate, the |
84 raised. For printing anything more serious and elaborate, the |
86 function @{ML tracing} should be used. This function writes all output into |
85 function @{ML tracing} should be used. This function writes all output into |
87 a separate tracing buffer. For example |
86 a separate tracing buffer. For example |
88 |
87 |
89 @{ML [display] "tracing \"foo\""} |
88 @{ML [display] "tracing \"foo\""} |
90 |
89 |
91 It is also possible to redirect the channel where the @{ML_text "foo"} is |
90 It is also possible to redirect the ``channel'' where the @{ML_text "foo"} is |
92 printed to a separate file, e.g. to prevent Proof General from choking on massive |
91 printed to a separate file, e.g. to prevent Proof General from choking on massive |
93 amounts of trace output. This rediretion can be achieved using the code |
92 amounts of trace output. This rediretion can be achieved using the code |
94 *} |
93 *} |
95 |
94 |
96 ML{* |
95 ML{* |
154 In a similar way you can use antiquotations to refer to theorems or simpsets: |
153 In a similar way you can use antiquotations to refer to theorems or simpsets: |
155 |
154 |
156 @{ML [display] "@{thm allI}"} |
155 @{ML [display] "@{thm allI}"} |
157 @{ML [display] "@{simpset}"} |
156 @{ML [display] "@{simpset}"} |
158 |
157 |
159 While antiquotations nowadays have many applications, they were originally introduced to |
158 While antiquotations have many applications, they were originally introduced to |
160 avoid explicit bindings for theorems such as |
159 avoid explicit bindings for theorems such as |
161 *} |
160 *} |
162 |
161 |
163 ML {* |
162 ML {* |
164 val allI = thm "allI" |
163 val allI = thm "allI" |
166 |
165 |
167 text {* |
166 text {* |
168 These bindings were difficult to maintain and also could be accidentally |
167 These bindings were difficult to maintain and also could be accidentally |
169 overwritten by the user. This usually broke definitional |
168 overwritten by the user. This usually broke definitional |
170 packages. Antiquotations solve this problem, since they are ``linked'' |
169 packages. Antiquotations solve this problem, since they are ``linked'' |
171 statically at compile-time. However, that also sometimes limits there |
170 statically at compile-time. However, that also sometimes limits their |
172 applicability. In the course of this introduction, we will learn more about |
171 applicability. In the course of this introduction, we will learn more about |
173 these antiquotations: they greatly simplify Isabelle programming since one |
172 these antiquotations: they greatly simplify Isabelle programming since one |
174 can directly access all kinds of logical elements from ML. |
173 can directly access all kinds of logical elements from ML. |
175 |
174 |
176 *} |
175 *} |
182 \mbox{@{text "@{term \<dots>}"}}. For example |
181 \mbox{@{text "@{term \<dots>}"}}. For example |
183 |
182 |
184 @{ML_response [display] "@{term \"(a::nat) + b = c\"}" |
183 @{ML_response [display] "@{term \"(a::nat) + b = c\"}" |
185 "Const (\"op =\", \<dots>) $ (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"} |
184 "Const (\"op =\", \<dots>) $ (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"} |
186 |
185 |
187 This will show the term @{term "(a::nat) + b = c"}, but printed out using the internal |
186 This will show the term @{term "(a::nat) + b = c"}, but printed using the internal |
188 representation of this term. This internal representation corresponds to the |
187 representation of this term. This internal representation corresponds to the |
189 datatype @{ML_type "term"}. |
188 datatype @{ML_type "term"}. |
190 |
189 |
191 The internal representation of terms uses the usual de Bruijn index mechanism where bound |
190 The internal representation of terms uses the usual de Bruijn index mechanism where bound |
192 variables are represented by the constructor @{ML Bound}. The index in @{ML Bound} refers to |
191 variables are represented by the constructor @{ML Bound}. The index in @{ML Bound} refers to |
220 \end{exercise} |
219 \end{exercise} |
221 |
220 |
222 @{ML [display] "print_depth 50"} |
221 @{ML [display] "print_depth 50"} |
223 |
222 |
224 The antiquotation @{text "@{prop \<dots>}"} constructs terms of propositional type, |
223 The antiquotation @{text "@{prop \<dots>}"} constructs terms of propositional type, |
225 inserting the invisible @{text "Trueprop"} coercions whenever necessary. |
224 inserting the invisible @{text "Trueprop"}-coercions whenever necessary. |
226 Consider for example |
225 Consider for example |
227 |
226 |
228 @{ML_response [display] "@{term \"P x\"}" "Free (\"P\", \<dots>) $ Free (\"x\", \<dots>)"} |
227 @{ML_response [display] "@{term \"P x\"}" "Free (\"P\", \<dots>) $ Free (\"x\", \<dots>)"} |
229 @{ML_response [display] "@{prop \"P x\"}" |
228 @{ML_response [display] "@{prop \"P x\"}" |
230 "Const (\"Trueprop\", \<dots>) $ (Free (\"P\", \<dots>) $ Free (\"x\", \<dots>))"} |
229 "Const (\"Trueprop\", \<dots>) $ (Free (\"P\", \<dots>) $ Free (\"x\", \<dots>))"} |
232 which inserts the coercion in the latter case and |
231 which inserts the coercion in the latter case and |
233 |
232 |
234 @{ML_response [display] "@{term \"P x \<Longrightarrow> Q x\"}" "Const (\"==>\", \<dots>) $ \<dots> $ \<dots>"} |
233 @{ML_response [display] "@{term \"P x \<Longrightarrow> Q x\"}" "Const (\"==>\", \<dots>) $ \<dots> $ \<dots>"} |
235 @{ML_response [display] "@{prop \"P x \<Longrightarrow> Q x\"}" "Const (\"==>\", \<dots>) $ \<dots> $ \<dots>"} |
234 @{ML_response [display] "@{prop \"P x \<Longrightarrow> Q x\"}" "Const (\"==>\", \<dots>) $ \<dots> $ \<dots>"} |
236 |
235 |
237 which does not. |
236 which does not (since it is already constructed using the meta-implication). |
238 |
237 |
239 Types can be constructed using the antiquotation @{text "@{typ \<dots>}"}. For example |
238 Types can be constructed using the antiquotation @{text "@{typ \<dots>}"}. For example |
240 |
239 |
241 @{ML_response_fake [display] "@{typ \"bool \<Rightarrow> nat\"}" "bool \<Rightarrow> nat"} |
240 @{ML_response_fake [display] "@{typ \"bool \<Rightarrow> nat\"}" "bool \<Rightarrow> nat"} |
242 |
241 |
281 text {* |
280 text {* |
282 To see this apply @{text "@{term S}"}, @{text "@{term T}"} and @{text "@{typ nat}"} |
281 To see this apply @{text "@{term S}"}, @{text "@{term T}"} and @{text "@{typ nat}"} |
283 to both functions. |
282 to both functions. |
284 |
283 |
285 One tricky point in constructing terms by hand is to obtain the |
284 One tricky point in constructing terms by hand is to obtain the |
286 fully qualified name for constants. For example the names for @{text "zero"} or |
285 fully qualified name for constants. For example the names for @{text "zero"} and |
287 @{text "+"} are more complex than one first expects, namely |
286 @{text "+"} are more complex than one first expects, namely |
288 |
287 |
289 \begin{center} |
288 \begin{center} |
290 @{ML_text "HOL.zero_class.zero"} and @{ML_text "HOL.plus_class.plus"}. |
289 @{ML_text "HOL.zero_class.zero"} and @{ML_text "HOL.plus_class.plus"}. |
291 \end{center} |
290 \end{center} |
298 |
297 |
299 @{ML_response_fake [display] "@{const_name \"Nil\"}" "List.list.Nil"} |
298 @{ML_response_fake [display] "@{const_name \"Nil\"}" "List.list.Nil"} |
300 |
299 |
301 (FIXME: Is it useful to explain @{text "@{const_syntax}"}?) |
300 (FIXME: Is it useful to explain @{text "@{const_syntax}"}?) |
302 |
301 |
303 Similarly, types can be constructed for example as follows: |
302 Similarly, types can be constructed manually, for example as follows: |
304 |
303 |
305 *} |
304 *} |
306 |
305 |
307 ML {* |
306 ML {* |
308 fun make_fun_type tau1 tau2 = Type ("fun",[tau1,tau2]) |
307 fun make_fun_type tau1 tau2 = Type ("fun",[tau1,tau2]) |
350 text {* |
349 text {* |
351 |
350 |
352 We can freely construct and manipulate terms, since they are just |
351 We can freely construct and manipulate terms, since they are just |
353 arbitrary unchecked trees. However, we eventually want to see if a |
352 arbitrary unchecked trees. However, we eventually want to see if a |
354 term is well-formed, or type checks, relative to a theory. |
353 term is well-formed, or type checks, relative to a theory. |
355 Type-checking is done via the function @{ML cterm_of}, which turns |
354 Type-checking is done via the function @{ML cterm_of}, which converts |
356 a @{ML_type term} into a @{ML_type cterm}, a \emph{certified} term. |
355 a @{ML_type term} into a @{ML_type cterm}, a \emph{certified} term. |
357 Unlike @{ML_type term}s, which are just trees, @{ML_type |
356 Unlike @{ML_type term}s, which are just trees, @{ML_type |
358 "cterm"}s are abstract objects that are guaranteed to be |
357 "cterm"}s are abstract objects that are guaranteed to be |
359 type-correct, and that can only be constructed via the official |
358 type-correct, and that can only be constructed via the ``official |
360 interfaces. |
359 interfaces''. |
361 |
360 |
362 Type checking is always relative to a theory context. For now we can use |
361 Type checking is always relative to a theory context. For now we use |
363 the @{ML "@{theory}"} antiquotation to get hold of the current theory. |
362 the @{ML "@{theory}"} antiquotation to get hold of the current theory. |
364 For example we can write |
363 For example we can write |
365 |
364 |
366 @{ML_response_fake [display] "cterm_of @{theory} @{term \"a + b = c\"}" "a + b = c"} |
365 @{ML_response_fake [display] "cterm_of @{theory} @{term \"a + b = c\"}" "a + b = c"} |
367 |
366 |
381 $ zero $ zero) |
380 $ zero $ zero) |
382 end" "0 + 0"} |
381 end" "0 + 0"} |
383 |
382 |
384 \begin{exercise} |
383 \begin{exercise} |
385 Check that the function defined in Exercise~\ref{fun:revsum} returns a |
384 Check that the function defined in Exercise~\ref{fun:revsum} returns a |
386 result that type checks. |
385 result that type-checks. |
387 \end{exercise} |
386 \end{exercise} |
388 |
387 |
389 *} |
388 *} |
390 |
389 |
391 section {* Theorems *} |
390 section {* Theorems *} |
392 |
391 |
393 text {* |
392 text {* |
394 Just like @{ML_type cterm}s, theorems (of type @{ML_type thm}) are |
393 Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} |
395 abstract objects that can only be built by going through the kernel |
394 that can only be built by going through interfaces, which means that all your proofs |
396 interfaces, which means that all your proofs will be checked. |
395 will be checked. |
397 |
396 |
398 To see theorems in ``action'', let us give a proof for the following statement |
397 To see theorems in ``action'', let us give a proof for the following statement |
399 *} |
398 *} |
400 |
399 |
401 lemma |
400 lemma |
467 |
466 |
468 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the open |
467 where @{term C} is the goal to be proved and the @{term "A\<^isub>i"} are the open |
469 subgoals. |
468 subgoals. |
470 Since the goal @{term C} can potentially be an implication, there is a |
469 Since the goal @{term C} can potentially be an implication, there is a |
471 @{text "#"} wrapped around it, which prevents that premises are |
470 @{text "#"} wrapped around it, which prevents that premises are |
472 misinterpreted as open subgoals. The protection @{text "# :: prop \<Rightarrow> |
471 misinterpreted as open subgoals. The wrapper @{text "# :: prop \<Rightarrow> |
473 prop"} is just the identity function and used as a syntactic marker. |
472 prop"} is just the identity function and used as a syntactic marker. |
474 |
473 |
475 \begin{readmore} |
474 \begin{readmore} |
476 For more on goals see \isccite{sec:tactical-goals}. |
475 For more on goals see \isccite{sec:tactical-goals}. |
477 \end{readmore} |
476 \end{readmore} |
482 |
481 |
483 \begin{readmore} |
482 \begin{readmore} |
484 See @{ML_file "Pure/General/seq.ML"} for the implementation of lazy |
483 See @{ML_file "Pure/General/seq.ML"} for the implementation of lazy |
485 sequences. However in day-to-day Isabelle programming, one rarely |
484 sequences. However in day-to-day Isabelle programming, one rarely |
486 constructs sequences explicitly, but uses the predefined tactic |
485 constructs sequences explicitly, but uses the predefined tactic |
487 combinators (tacticals) instead (see @{ML_file "Pure/tctical.ML"}). |
486 combinators (tacticals) instead. See @{ML_file "Pure/tctical.ML"} |
488 (FIXME: Pointer to the old reference manual) |
487 for the code; see Chapters 3 and 4 in the old Isabelle Reference Manual. |
489 \end{readmore} |
488 \end{readmore} |
490 |
489 |
491 While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they |
490 While tactics can operate on the subgoals (the @{text "A\<^isub>i"} above), they |
492 are expected to leave the conclusion @{term C} intact, with the |
491 are expected to leave the conclusion @{term C} intact, with the |
493 exception of possibly instantiating schematic variables. |
492 exception of possibly instantiating schematic variables. |
494 |
493 |
495 To see how tactics work, let us transcribe a simple @{text apply}-style |
494 To see how tactics work, let us transcribe a simple @{text apply}-style |
496 proof from the tutorial~\cite{isa-tutorial} into ML: |
495 proof into ML: |
497 *} |
496 *} |
498 |
497 |
499 lemma disj_swap: "P \<or> Q \<Longrightarrow> Q \<or> P" |
498 lemma disj_swap: "P \<or> Q \<Longrightarrow> Q \<or> P" |
500 apply (erule disjE) |
499 apply (erule disjE) |
501 apply (rule disjI2) |
500 apply (rule disjI2) |
508 To start the proof, the function @{ML "Goal.prove"}~@{text "ctxt xs As C tac"} sets |
507 To start the proof, the function @{ML "Goal.prove"}~@{text "ctxt xs As C tac"} sets |
509 up a goal state for proving the goal @{text C} under the assumptions @{text As} |
508 up a goal state for proving the goal @{text C} under the assumptions @{text As} |
510 (empty in the proof at hand) |
509 (empty in the proof at hand) |
511 with the variables @{text xs} that will be generalised once the |
510 with the variables @{text xs} that will be generalised once the |
512 goal is proved. The @{text "tac"} is the tactic which proves the goal and which |
511 goal is proved. The @{text "tac"} is the tactic which proves the goal and which |
513 can make use of the local assumptions. |
512 can make use of the local assumptions (there are none in this example). |
514 |
513 |
515 @{ML_response_fake [display] |
514 @{ML_response_fake [display] |
516 "let |
515 "let |
517 val ctxt = @{context} |
516 val ctxt = @{context} |
518 val goal = @{prop \"P \<or> Q \<Longrightarrow> Q \<or> P\"} |
517 val goal = @{prop \"P \<or> Q \<Longrightarrow> Q \<or> P\"} |