3 begin |
3 begin |
4 |
4 |
5 chapter {* Let's Talk About the Good, the Bad and the Ugly *} |
5 chapter {* Let's Talk About the Good, the Bad and the Ugly *} |
6 |
6 |
7 text {* |
7 text {* |
8 Isabelle is build around a few central ideas. One is the LCF-approach to |
8 Isabelle is build around a few central ideas. One central idea is the |
9 theorem proving where there is a small trusted core and everything else is |
9 LCF-approach to theorem proving where there is a small trusted core and |
10 build on top of this trusted core. The central data structures involved |
10 everything else is build on top of this trusted core. The fundamental data |
11 in this core are certified terms and types as well as theorems. |
11 structures involved in this core are certified terms and types, as well as |
|
12 theorems. |
12 *} |
13 *} |
13 |
14 |
14 |
15 |
15 section {* Terms and Types *} |
16 section {* Terms and Types *} |
16 |
17 |
17 text {* |
18 text {* |
18 In Isabelle there are certified terms (respectively types) and uncertified |
19 There are certified terms and uncertified terms (respectively types). |
19 terms. The latter are called just terms. One way to construct them is by |
20 Uncertified terms are just called terms. One way to construct them is by |
20 using the antiquotation \mbox{@{text "@{term \<dots>}"}}. For example |
21 using the antiquotation \mbox{@{text "@{term \<dots>}"}}. For example |
21 |
22 |
22 @{ML_response [display,gray] |
23 @{ML_response [display,gray] |
23 "@{term \"(a::nat) + b = c\"}" |
24 "@{term \"(a::nat) + b = c\"}" |
24 "Const (\"op =\", \<dots>) $ |
25 "Const (\"op =\", \<dots>) $ |
25 (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"} |
26 (Const (\"HOL.plus_class.plus\", \<dots>) $ \<dots> $ \<dots>) $ \<dots>"} |
26 |
27 |
27 will show the term @{term "(a::nat) + b = c"}, but printed using the internal |
28 constructs the term @{term "(a::nat) + b = c"}, but it printed using the internal |
28 representation corresponding to the datatype @{ML_type "term"} defined as follows: |
29 representation corresponding to the datatype @{ML_type_ind "term"} defined as follows: |
29 *} |
30 *} |
30 |
31 |
31 ML_val %linenosgray{*datatype term = |
32 ML_val %linenosgray{*datatype term = |
32 Const of string * typ |
33 Const of string * typ |
33 | Free of string * typ |
34 | Free of string * typ |
35 | Bound of int |
36 | Bound of int |
36 | Abs of string * typ * term |
37 | Abs of string * typ * term |
37 | $ of term * term *} |
38 | $ of term * term *} |
38 |
39 |
39 text {* |
40 text {* |
40 This datatype implements lambda-terms typed in Church-style. |
41 This datatype implements Church-style lambda-terms, where types are |
41 As can be seen in Line 5, terms use the usual de Bruijn index mechanism |
42 explicitly recorded in the variables, constants and abstractions. As can be |
42 for representing bound variables. For |
43 seen in Line 5, terms use the usual de Bruijn index mechanism for |
43 example in |
44 representing bound variables. For example in |
44 |
45 |
45 @{ML_response_fake [display, gray] |
46 @{ML_response_fake [display, gray] |
46 "@{term \"\<lambda>x y. x y\"}" |
47 "@{term \"\<lambda>x y. x y\"}" |
47 "Abs (\"x\", \"'a \<Rightarrow> 'b\", Abs (\"y\", \"'a\", Bound 1 $ Bound 0))"} |
48 "Abs (\"x\", \"'a \<Rightarrow> 'b\", Abs (\"y\", \"'a\", Bound 1 $ Bound 0))"} |
48 |
49 |
73 |
74 |
74 When constructing terms, you are usually concerned with free variables (as |
75 When constructing terms, you are usually concerned with free variables (as |
75 mentioned earlier, you cannot construct schematic variables using the |
76 mentioned earlier, you cannot construct schematic variables using the |
76 antiquotation @{text "@{term \<dots>}"}). If you deal with theorems, you have to, |
77 antiquotation @{text "@{term \<dots>}"}). If you deal with theorems, you have to, |
77 however, observe the distinction. The reason is that only schematic |
78 however, observe the distinction. The reason is that only schematic |
78 varaibles can be instantiated with terms when a theorem is applied. A |
79 variables can be instantiated with terms when a theorem is applied. A |
79 similar distinction between free and schematic variables holds for types |
80 similar distinction between free and schematic variables holds for types |
80 (see below). |
81 (see below). |
81 |
82 |
82 \begin{readmore} |
83 \begin{readmore} |
83 Terms and types are described in detail in \isccite{sec:terms}. Their |
84 Terms and types are described in detail in \isccite{sec:terms}. Their |
95 |
96 |
96 raises a typing error, while it perfectly ok to construct the term |
97 raises a typing error, while it perfectly ok to construct the term |
97 |
98 |
98 @{ML_response_fake [display,gray] |
99 @{ML_response_fake [display,gray] |
99 "let |
100 "let |
100 val omega = Free (\"x\", @{typ nat}) $ Free (\"x\", @{typ nat}) |
101 val omega = Free (\"x\", @{typ \"nat \<Rightarrow> nat\"}) $ Free (\"x\", @{typ nat}) |
101 in |
102 in |
102 tracing (string_of_term @{context} omega) |
103 tracing (string_of_term @{context} omega) |
103 end" |
104 end" |
104 "x x"} |
105 "x x"} |
105 |
106 |
222 "Const \<dots> $ |
223 "Const \<dots> $ |
223 Abs (\"x\", \<dots>, |
224 Abs (\"x\", \<dots>, |
224 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
225 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
225 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
226 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
226 |
227 |
227 There are a number of handy functions that are frequently used for |
228 There are a number of handy functions that are frequently used for |
228 constructing terms. One is the function @{ML_ind list_comb}, which takes a term |
229 constructing terms. One is the function @{ML_ind list_comb in Term}, which |
229 and a list of terms as arguments, and produces as output the term |
230 takes a term and a list of terms as arguments, and produces as output the |
230 list applied to the term. For example |
231 term list applied to the term. For example |
|
232 |
231 |
233 |
232 @{ML_response_fake [display,gray] |
234 @{ML_response_fake [display,gray] |
233 "let |
235 "let |
234 val trm = @{term \"P::nat\"} |
236 val trm = @{term \"P::nat\"} |
235 val args = [@{term \"True\"}, @{term \"False\"}] |
237 val args = [@{term \"True\"}, @{term \"False\"}] |
236 in |
238 in |
237 list_comb (trm, args) |
239 list_comb (trm, args) |
238 end" |
240 end" |
239 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
241 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
240 |
242 |
241 Another handy function is @{ML_ind lambda}, which abstracts a variable |
243 Another handy function is @{ML_ind lambda in Term}, which abstracts a variable |
242 in a term. For example |
244 in a term. For example |
243 |
245 |
244 @{ML_response_fake [display,gray] |
246 @{ML_response_fake [display,gray] |
245 "let |
247 "let |
246 val x_nat = @{term \"x::nat\"} |
248 val x_nat = @{term \"x::nat\"} |
269 then the variable @{text "Free (\"x\", \"int\")"} is \emph{not} abstracted. |
271 then the variable @{text "Free (\"x\", \"int\")"} is \emph{not} abstracted. |
270 This is a fundamental principle |
272 This is a fundamental principle |
271 of Church-style typing, where variables with the same name still differ, if they |
273 of Church-style typing, where variables with the same name still differ, if they |
272 have different type. |
274 have different type. |
273 |
275 |
274 There is also the function @{ML_ind subst_free} with which terms can be |
276 There is also the function @{ML_ind subst_free in Term} with which terms can be |
275 replaced by other terms. For example below, we will replace in @{term |
277 replaced by other terms. For example below, we will replace in @{term |
276 "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0 x"} the subterm @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0"} by |
278 "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0 x"} the subterm @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0"} by |
277 @{term y}, and @{term x} by @{term True}. |
279 @{term y}, and @{term x} by @{term True}. |
278 |
280 |
279 @{ML_response_fake [display,gray] |
281 @{ML_response_fake [display,gray] |
296 in |
298 in |
297 subst_free [sub] trm |
299 subst_free [sub] trm |
298 end" |
300 end" |
299 "Free (\"x\", \"nat\")"} |
301 "Free (\"x\", \"nat\")"} |
300 |
302 |
301 Similarly the function @{ML_ind subst_bounds}, replaces lose bound |
303 Similarly the function @{ML_ind subst_bounds in Term}, replaces lose bound |
302 variables with terms. To see how this function works, let us implement a |
304 variables with terms. To see how this function works, let us implement a |
303 function that strips off the outermost quantifiers in a term. |
305 function that strips off the outermost quantifiers in a term. |
304 *} |
306 *} |
305 |
307 |
306 ML{*fun strip_alls (Const ("All", _) $ Abs (n, T, t)) = |
308 ML{*fun strip_alls (Const ("All", _) $ Abs (n, T, t)) = |
307 strip_alls t |>> cons (Free (n, T)) |
309 strip_alls t |>> cons (Free (n, T)) |
308 | strip_alls t = ([], t) *} |
310 | strip_alls t = ([], t) *} |
309 |
311 |
310 text {* |
312 text {* |
311 The function returns a pair consisting of the stripped off variables and |
313 The function returns a pair consisting of the stripped off variables and |
312 the body of the universal quantifications. For example |
314 the body of the universal quantifications. For example |
316 "([Free (\"x\", \"bool\"), Free (\"y\", \"bool\")], |
318 "([Free (\"x\", \"bool\"), Free (\"y\", \"bool\")], |
317 Const (\"op =\", \<dots>) $ Bound 1 $ Bound 0)"} |
319 Const (\"op =\", \<dots>) $ Bound 1 $ Bound 0)"} |
318 |
320 |
319 After calling @{ML strip_alls}, you obtain a term with lose bound variables. With |
321 After calling @{ML strip_alls}, you obtain a term with lose bound variables. With |
320 the function @{ML subst_bounds}, you can replace these lose @{ML_ind |
322 the function @{ML subst_bounds}, you can replace these lose @{ML_ind |
321 Bound}s with the stripped off variables. |
323 Bound in Term}s with the stripped off variables. |
322 |
324 |
323 @{ML_response_fake [display, gray, linenos] |
325 @{ML_response_fake [display, gray, linenos] |
324 "let |
326 "let |
325 val (vrs, trm) = strip_alls @{term \"\<forall>x y. x = (y::bool)\"} |
327 val (vrs, trm) = strip_alls @{term \"\<forall>x y. x = (y::bool)\"} |
326 in |
328 in |
334 returned. The reason is that the head of the list the function @{ML subst_bounds} |
336 returned. The reason is that the head of the list the function @{ML subst_bounds} |
335 takes is the replacement for @{ML "Bound 0"}, the next element for @{ML "Bound 1"} |
337 takes is the replacement for @{ML "Bound 0"}, the next element for @{ML "Bound 1"} |
336 and so on. |
338 and so on. |
337 |
339 |
338 There are many convenient functions that construct specific HOL-terms. For |
340 There are many convenient functions that construct specific HOL-terms. For |
339 example @{ML_ind mk_eq in HOLogic} constructs an equality out of two terms. |
341 example @{ML_ind mk_eq in HOLogic} constructs an equality out of two terms. |
340 The types needed in this equality are calculated from the type of the |
342 The types needed in this equality are calculated from the type of the |
341 arguments. For example |
343 arguments. For example |
342 |
344 |
343 @{ML_response_fake [gray,display] |
345 @{ML_response_fake [gray,display] |
344 "let |
346 "let |
449 |
451 |
450 \footnote{\bf FIXME: Explain the following better; maybe put in a separate |
452 \footnote{\bf FIXME: Explain the following better; maybe put in a separate |
451 section and link with the comment in the antiquotation section.} |
453 section and link with the comment in the antiquotation section.} |
452 |
454 |
453 Occasionally you have to calculate what the ``base'' name of a given |
455 Occasionally you have to calculate what the ``base'' name of a given |
454 constant is. For this you can use the function @{ML_ind "Sign.extern_const"} or |
456 constant is. For this you can use the function @{ML_ind "Sign.extern_const"} or |
455 @{ML_ind Long_Name.base_name}. For example: |
457 @{ML_ind Long_Name.base_name}. For example: |
456 |
458 |
457 @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""} |
459 @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""} |
458 |
460 |
459 The difference between both functions is that @{ML extern_const in Sign} returns |
461 The difference between both functions is that @{ML extern_const in Sign} returns |
472 |
474 |
473 *} |
475 *} |
474 |
476 |
475 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *} |
477 ML{*fun make_fun_type ty1 ty2 = Type ("fun", [ty1, ty2]) *} |
476 |
478 |
477 text {* This can be equally written with the combinator @{ML_ind "-->"} as: *} |
479 text {* This can be equally written with the combinator @{ML_ind "-->" in Term} as: *} |
478 |
480 |
479 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *} |
481 ML{*fun make_fun_type ty1 ty2 = ty1 --> ty2 *} |
480 |
482 |
481 text {* |
483 text {* |
482 If you want to construct a function type with more than one argument |
484 If you want to construct a function type with more than one argument |
483 type, then you can use @{ML_ind "--->"}. |
485 type, then you can use @{ML_ind "--->" in Term}. |
484 *} |
486 *} |
485 |
487 |
486 ML{*fun make_fun_types tys ty = tys ---> ty *} |
488 ML{*fun make_fun_types tys ty = tys ---> ty *} |
487 |
489 |
488 text {* |
490 text {* |
605 where no error is detected. |
607 where no error is detected. |
606 |
608 |
607 Sometimes it is a bit inconvenient to construct a term with |
609 Sometimes it is a bit inconvenient to construct a term with |
608 complete typing annotations, especially in cases where the typing |
610 complete typing annotations, especially in cases where the typing |
609 information is redundant. A short-cut is to use the ``place-holder'' |
611 information is redundant. A short-cut is to use the ``place-holder'' |
610 type @{ML_ind dummyT} and then let type-inference figure out the |
612 type @{ML_ind dummyT in Term} and then let type-inference figure out the |
611 complete type. An example is as follows: |
613 complete type. An example is as follows: |
612 |
614 |
613 @{ML_response_fake [display,gray] |
615 @{ML_response_fake [display,gray] |
614 "let |
616 "let |
615 val c = Const (@{const_name \"plus\"}, dummyT) |
617 val c = Const (@{const_name \"plus\"}, dummyT) |