41 evaluated by using the advance and undo buttons of your Isabelle |
41 evaluated by using the advance and undo buttons of your Isabelle |
42 environment. The code inside the \isacommand{ML}-command can also contain |
42 environment. The code inside the \isacommand{ML}-command can also contain |
43 value and function bindings, and even those can be undone when the proof |
43 value and function bindings, and even those can be undone when the proof |
44 script is retracted. As mentioned earlier, we will drop the |
44 script is retracted. As mentioned earlier, we will drop the |
45 \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"} scaffolding whenever we |
45 \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"} scaffolding whenever we |
46 show code. The lines prefixed with @{text ">"} are not part of the |
46 show code. The lines prefixed with @{text [quotes] ">"} are not part of the |
47 code, rather they indicate what the response is when the code is evaluated. |
47 code, rather they indicate what the response is when the code is evaluated. |
48 |
48 |
49 Once a portion of code is relatively stable, you usually want to export it |
49 Once a portion of code is relatively stable, you usually want to export it |
50 to a separate ML-file. Such files can then be included in a theory by using |
50 to a separate ML-file. Such files can then be included in a theory by using |
51 the \isacommand{uses}-command in the header of the theory, like: |
51 the \isacommand{uses}-command in the header of the theory, like: |
73 @{ML_response_fake [display,gray] "warning \"any string\"" "\"any string\""} |
73 @{ML_response_fake [display,gray] "warning \"any string\"" "\"any string\""} |
74 |
74 |
75 will print out @{text [quotes] "any string"} inside the response buffer |
75 will print out @{text [quotes] "any string"} inside the response buffer |
76 of Isabelle. This function expects a string as argument. If you develop under PolyML, |
76 of Isabelle. This function expects a string as argument. If you develop under PolyML, |
77 then there is a convenient, though again ``quick-and-dirty'', method for |
77 then there is a convenient, though again ``quick-and-dirty'', method for |
78 converting values into strings, namely using the function @{ML makestring}: |
78 converting values into strings, namely the function @{ML makestring}: |
79 |
79 |
80 @{ML_response_fake [display,gray] "warning (makestring 1)" "\"1\""} |
80 @{ML_response_fake [display,gray] "warning (makestring 1)" "\"1\""} |
81 |
81 |
82 However @{ML makestring} only works if the type of what is converted is monomorphic |
82 However @{ML makestring} only works if the type of what is converted is monomorphic |
83 and not a function. |
83 and not a function. |
90 |
90 |
91 @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""} |
91 @{ML_response_fake [display,gray] "tracing \"foo\"" "\"foo\""} |
92 |
92 |
93 It is also possible to redirect the ``channel'' where the string @{text "foo"} is |
93 It is also possible to redirect the ``channel'' where the string @{text "foo"} is |
94 printed to a separate file, e.g.~to prevent ProofGeneral from choking on massive |
94 printed to a separate file, e.g.~to prevent ProofGeneral from choking on massive |
95 amounts of trace output. This redirection can be achieved using the code |
95 amounts of trace output. This redirection can be achieved with the code: |
96 *} |
96 *} |
97 |
97 |
98 ML{*val strip_specials = |
98 ML{*val strip_specials = |
99 let |
99 let |
100 fun strip ("\^A" :: _ :: cs) = strip cs |
100 fun strip ("\^A" :: _ :: cs) = strip cs |
110 |
110 |
111 text {* |
111 text {* |
112 Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} |
112 Calling @{ML "redirect_tracing"} with @{ML "(TextIO.openOut \"foo.bar\")"} |
113 will cause that all tracing information is printed into the file @{text "foo.bar"}. |
113 will cause that all tracing information is printed into the file @{text "foo.bar"}. |
114 |
114 |
115 You can print out error messages with the function @{ML error}, as in: |
115 You can print out error messages with the function @{ML error}; for example: |
116 |
116 |
117 @{ML_response_fake [display,gray] "if 0=1 then 1 else (error \"foo\")" "\"foo\""} |
117 @{ML_response_fake [display,gray] "if 0=1 then 1 else (error \"foo\")" "\"foo\""} |
118 |
118 |
119 Section~\ref{sec:printing} will give more information about printing |
119 Section~\ref{sec:printing} will give more information about printing |
120 the main datas tructures of Isabelle, namely @{ML_type term}, @{ML_type cterm} |
120 the main data structures of Isabelle, namely @{ML_type term}, @{ML_type cterm} |
121 and @{ML_type thm}. |
121 and @{ML_type thm}. |
122 *} |
122 *} |
123 |
123 |
124 |
124 |
125 |
125 |
159 |
159 |
160 In a similar way you can use antiquotations to refer to proved theorems: |
160 In a similar way you can use antiquotations to refer to proved theorems: |
161 |
161 |
162 @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"} |
162 @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"} |
163 |
163 |
164 or simpsets: |
164 and simpsets: |
165 |
165 |
166 @{ML_response_fake [display,gray] |
166 @{ML_response_fake [display,gray] |
167 "let |
167 "let |
168 val ({rules,...}, _) = MetaSimplifier.rep_ss @{simpset} |
168 val ({rules,...}, _) = MetaSimplifier.rep_ss @{simpset} |
169 in |
169 in |
383 Write a function which takes two terms representing natural numbers |
383 Write a function which takes two terms representing natural numbers |
384 in unary notation (like @{term "Suc (Suc (Suc 0))"}), and produce the |
384 in unary notation (like @{term "Suc (Suc (Suc 0))"}), and produce the |
385 number representing their sum. |
385 number representing their sum. |
386 \end{exercise} |
386 \end{exercise} |
387 |
387 |
388 (FIXME: maybe should go) |
388 A handy function for manipulating terms is @{ML map_types}: it takes a |
389 |
389 function and applies it to every type in the term. You can, for example, |
|
390 change every @{typ nat} into an @{typ int} using the function |
390 *} |
391 *} |
391 |
392 |
392 ML{*fun nat_to_int t = |
393 ML{*fun nat_to_int t = |
393 (case t of |
394 (case t of |
394 @{typ nat} => @{typ int} |
395 @{typ nat} => @{typ int} |
395 | Type (s, ts) => Type (s, map nat_to_int ts) |
396 | Type (s, ts) => Type (s, map nat_to_int ts) |
396 | _ => t)*} |
397 | _ => t)*} |
397 |
398 |
398 text {* |
399 text {* |
|
400 an then apply it as follows: |
|
401 |
399 |
402 |
400 @{ML_response_fake [display,gray] |
403 @{ML_response_fake [display,gray] |
401 "map_types nat_to_int @{term \"a = (1::nat)\"}" |
404 "map_types nat_to_int @{term \"a = (1::nat)\"}" |
402 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\") |
405 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\") |
403 $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"} |
406 $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"} |
422 the @{ML "@{theory}"} antiquotation to get hold of the current theory. |
425 the @{ML "@{theory}"} antiquotation to get hold of the current theory. |
423 For example you can write: |
426 For example you can write: |
424 |
427 |
425 @{ML_response_fake [display,gray] "cterm_of @{theory} @{term \"a + b = c\"}" "a + b = c"} |
428 @{ML_response_fake [display,gray] "cterm_of @{theory} @{term \"a + b = c\"}" "a + b = c"} |
426 |
429 |
427 This can also be wirtten with an antiquotation: |
430 This can also be written with an antiquotation: |
428 |
431 |
429 @{ML_response_fake [display,gray] "@{cterm \"(a::nat) + b = c\"}" "a + b = c"} |
432 @{ML_response_fake [display,gray] "@{cterm \"(a::nat) + b = c\"}" "a + b = c"} |
430 |
433 |
431 Attempting to obtain the certified term for |
434 Attempting to obtain the certified term for |
432 |
435 |
456 section {* Theorems *} |
459 section {* Theorems *} |
457 |
460 |
458 text {* |
461 text {* |
459 Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} |
462 Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} |
460 that can only be built by going through interfaces. As a consequence, every proof |
463 that can only be built by going through interfaces. As a consequence, every proof |
461 in Isabelle is correct by construction (FIXME reference LCF-philosophy) |
464 in Isabelle is correct by construction. |
|
465 |
|
466 (FIXME reference LCF-philosophy) |
462 |
467 |
463 To see theorems in ``action'', let us give a proof on the ML-level for the following |
468 To see theorems in ``action'', let us give a proof on the ML-level for the following |
464 statement: |
469 statement: |
465 *} |
470 *} |
466 |
471 |
523 section {* Theorem Attributes *} |
528 section {* Theorem Attributes *} |
524 |
529 |
525 section {* Printing Terms and Theorems\label{sec:printing} *} |
530 section {* Printing Terms and Theorems\label{sec:printing} *} |
526 |
531 |
527 text {* |
532 text {* |
528 During development, you often want to inspect terms, cterms |
533 During development, you often want to inspect date of type @{ML_type term}, @{ML_type cterm} |
529 or theorems. Isabelle contains elaborate pretty-printing functions for printing them, |
534 or @{ML_type thm}. Isabelle contains elaborate pretty-printing functions for printing them, |
530 but for quick-and-dirty solutions they are far too unwieldy. A simple way to transform |
535 but for quick-and-dirty solutions they are far too unwieldy. A simple way to transform |
531 a term into a string is to use the function @{ML Syntax.string_of_term}. |
536 a term into a string is to use the function @{ML Syntax.string_of_term}. |
532 |
537 |
533 @{ML_response_fake [display,gray] |
538 @{ML_response_fake [display,gray] |
534 "Syntax.string_of_term @{context} @{term \"1::nat\"}" |
539 "Syntax.string_of_term @{context} @{term \"1::nat\"}" |
535 "\"\\^E\\^Fterm\\^E\\^E\\^Fconst\\^Fname=HOL.one_class.one\\^E1\\^E\\^F\\^E\\^E\\^F\\^E\""} |
540 "\"\\^E\\^Fterm\\^E\\^E\\^Fconst\\^Fname=HOL.one_class.one\\^E1\\^E\\^F\\^E\\^E\\^F\\^E\""} |
536 |
541 |
537 This produces a string with some printing directions encoded in it. The string |
542 This produces a string with some printing directions encoded in it. The string |
538 can be properly printed by using @{ML warning} foe example. |
543 can be properly printed by using the function @{ML warning}. |
539 |
544 |
540 @{ML_response_fake [display,gray] |
545 @{ML_response_fake [display,gray] |
541 "warning (Syntax.string_of_term @{context} @{term \"1::nat\"})" |
546 "warning (Syntax.string_of_term @{context} @{term \"1::nat\"})" |
542 "\"1\""} |
547 "\"1\""} |
543 |
548 |
744 This combinator is defined as |
749 This combinator is defined as |
745 *} |
750 *} |
746 |
751 |
747 ML{*fun (x, y) |-> f = f x y*} |
752 ML{*fun (x, y) |-> f = f x y*} |
748 |
753 |
749 text {* and can be used to write the following version of the @{text double} function *} |
754 text {* and can be used to write the following roundabout version |
|
755 of the @{text double} function |
|
756 *} |
750 |
757 |
751 ML{*fun double x = |
758 ML{*fun double x = |
752 x |> (fn x => (x, x)) |
759 x |> (fn x => (x, x)) |
753 |-> (fn x => fn y => x + y)*} |
760 |-> (fn x => fn y => x + y)*} |
754 |
761 |