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}; for example: |
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 true else (error \"foo\")" |
|
118 "Exception- ERROR \"foo\" raised |
|
119 At command \"ML\"."} |
118 |
120 |
119 Section~\ref{sec:printing} will give more information about printing |
121 Section~\ref{sec:printing} will give more information about printing |
120 the main data structures of Isabelle, namely @{ML_type term}, @{ML_type cterm} |
122 the main data structures of Isabelle, namely @{ML_type term}, @{ML_type cterm} |
121 and @{ML_type thm}. |
123 and @{ML_type thm}. |
122 *} |
124 *} |
123 |
|
124 |
|
125 |
125 |
126 |
126 |
127 section {* Antiquotations *} |
127 section {* Antiquotations *} |
128 |
128 |
129 text {* |
129 text {* |
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 and simpsets: |
164 and current 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 |
170 map #name (Net.entries rules) |
170 map #name (Net.entries rules) |
171 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"} |
171 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"} |
172 |
172 |
173 The code about simpsets extracts the theorem names stored in the |
173 The code about simpsets extracts the theorem names stored in the |
174 current simpset. You can get hold of the current simpset with the antiquotation |
174 simpset. You can get hold of the current simpset with the antiquotation |
175 @{text "@{simpset}"}. The function @{ML rep_ss in MetaSimplifier} returns a record |
175 @{text "@{simpset}"}. The function @{ML rep_ss in MetaSimplifier} returns a record |
176 containing all information about the simpset. The rules of a simpset are |
176 containing all information about the simpset. The rules of a simpset are |
177 stored in a \emph{discrimination net} (a data structure for fast |
177 stored in a \emph{discrimination net} (a data structure for fast |
178 indexing). From this net you can extract the entries using the function @{ML |
178 indexing). From this net you can extract the entries using the function @{ML |
179 Net.entries}. |
179 Net.entries}. |
195 These bindings are difficult to maintain and also can be accidentally |
195 These bindings are difficult to maintain and also can be accidentally |
196 overwritten by the user. This often breakes Isabelle |
196 overwritten by the user. This often breakes Isabelle |
197 packages. Antiquotations solve this problem, since they are ``linked'' |
197 packages. Antiquotations solve this problem, since they are ``linked'' |
198 statically at compile-time. However, this static linkage also limits their |
198 statically at compile-time. However, this static linkage also limits their |
199 usefulness in cases where data needs to be build up dynamically. In the |
199 usefulness in cases where data needs to be build up dynamically. In the |
200 course of this introduction, we will learn more about these antiquotations: |
200 course of this introduction, you will learn more about these antiquotations: |
201 they greatly simplify Isabelle programming since one can directly access all |
201 they can simplify Isabelle programming since one can directly access all |
202 kinds of logical elements from th ML-level. |
202 kinds of logical elements from th ML-level. |
203 |
203 |
204 *} |
204 *} |
205 |
205 |
206 section {* Terms and Types *} |
206 section {* Terms and Types *} |
207 |
207 |
208 text {* |
208 text {* |
209 One way to construct terms of Isabelle on the ML-level is by using the antiquotation |
209 One way to construct terms of Isabelle is by using the antiquotation |
210 \mbox{@{text "@{term \<dots>}"}}. For example: |
210 \mbox{@{text "@{term \<dots>}"}}. For example: |
211 |
211 |
212 @{ML_response [display,gray] |
212 @{ML_response [display,gray] |
213 "@{term \"(a::nat) + b = c\"}" |
213 "@{term \"(a::nat) + b = c\"}" |
214 "Const (\"op =\", \<dots>) $ |
214 "Const (\"op =\", \<dots>) $ |
243 \item @{term "{ [x::int] | x. x \<le> -2 }"} |
243 \item @{term "{ [x::int] | x. x \<le> -2 }"} |
244 \end{itemize} |
244 \end{itemize} |
245 |
245 |
246 Hint: The third term is already quite big, and the pretty printer |
246 Hint: The third term is already quite big, and the pretty printer |
247 may omit parts of it by default. If you want to see all of it, you |
247 may omit parts of it by default. If you want to see all of it, you |
248 can use the following ML-function to set the limit to a value high |
248 can use the following ML-function to set the printing depth to a higher |
249 enough: |
249 value: |
250 |
250 |
251 @{ML [display,gray] "print_depth 50"} |
251 @{ML [display,gray] "print_depth 50"} |
252 \end{exercise} |
252 \end{exercise} |
253 |
253 |
254 The antiquotation @{text "@{prop \<dots>}"} constructs terms of propositional type, |
254 The antiquotation @{text "@{prop \<dots>}"} constructs terms of propositional type, |
321 "Const \<dots> $ |
321 "Const \<dots> $ |
322 Abs (\"x\", \<dots>, |
322 Abs (\"x\", \<dots>, |
323 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
323 Const \<dots> $ (Const \<dots> $ (Free (\"P\",\<dots>) $ \<dots>)) $ |
324 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
324 (Const \<dots> $ (Free (\"Q\",\<dots>) $ \<dots>)))"} |
325 |
325 |
326 (FIXME: expand the following point) |
|
327 |
|
328 One tricky point in constructing terms by hand is to obtain the fully |
|
329 qualified name for constants. For example the names for @{text "zero"} and |
|
330 @{text "+"} are more complex than one first expects, namely |
|
331 |
|
332 |
|
333 \begin{center} |
|
334 @{text "HOL.zero_class.zero"} and @{text "HOL.plus_class.plus"}. |
|
335 \end{center} |
|
336 |
|
337 The extra prefixes @{text zero_class} and @{text plus_class} are present |
|
338 because these constants are defined within type classes; the prefix @{text |
|
339 "HOL"} indicates in which theory they are defined. Guessing such internal |
|
340 names can sometimes be quite hard. Therefore Isabelle provides the |
|
341 antiquotation @{text "@{const_name \<dots>}"} which does the expansion |
|
342 automatically, for example: |
|
343 |
|
344 @{ML_response_fake [display,gray] "@{const_name \"Nil\"}" "List.list.Nil"} |
|
345 |
|
346 (FIXME: Is it useful to explain @{text "@{const_syntax}"}?) |
|
347 |
|
348 Although types of terms can often be inferred, there are many |
326 Although types of terms can often be inferred, there are many |
349 situations where you need to construct types manually, especially |
327 situations where you need to construct types manually, especially |
350 when defining constants. For example the function returning a function |
328 when defining constants. For example the function returning a function |
351 type is as follows: |
329 type is as follows: |
352 |
330 |
357 text {* This can be equally written as: *} |
335 text {* This can be equally written as: *} |
358 |
336 |
359 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *} |
337 ML{*fun make_fun_type tau1 tau2 = tau1 --> tau2 *} |
360 |
338 |
361 text {* |
339 text {* |
362 |
|
363 \begin{readmore} |
340 \begin{readmore} |
364 There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and |
341 There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file "Pure/logic.ML"} and |
365 @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms |
342 @{ML_file "HOL/Tools/hologic.ML"} that make such manual constructions of terms |
366 and types easier.\end{readmore} |
343 and types easier.\end{readmore} |
367 |
344 |
368 Have a look at these files and try to solve the following two exercises: |
345 Have a look at these files and try to solve the following two exercises: |
369 |
|
370 *} |
346 *} |
371 |
347 |
372 text {* |
348 text {* |
373 |
349 |
374 \begin{exercise}\label{fun:revsum} |
350 \begin{exercise}\label{fun:revsum} |
375 Write a function @{text "rev_sum : term -> term"} that takes a |
351 Write a function @{text "rev_sum : term -> term"} that takes a |
376 term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} (whereby @{text "i"} might be zero) |
352 term of the form @{text "t\<^isub>1 + t\<^isub>2 + \<dots> + t\<^isub>n"} (whereby @{text "n"} might be zero) |
377 and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. Assume |
353 and returns the reversed sum @{text "t\<^isub>n + \<dots> + t\<^isub>2 + t\<^isub>1"}. Assume |
378 the @{text "t\<^isub>i"} can be arbitrary expressions and also note that @{text "+"} |
354 the @{text "t\<^isub>i"} can be arbitrary expressions and also note that @{text "+"} |
379 associates to the left. Try your function on some examples. |
355 associates to the left. Try your function on some examples. |
380 \end{exercise} |
356 \end{exercise} |
381 |
357 |
385 number representing their sum. |
361 number representing their sum. |
386 \end{exercise} |
362 \end{exercise} |
387 |
363 |
388 A handy function for manipulating terms is @{ML map_types}: it takes a |
364 A handy function for manipulating terms is @{ML map_types}: it takes a |
389 function and applies it to every type in the term. You can, for example, |
365 function and applies it to every type in the term. You can, for example, |
390 change every @{typ nat} in a term into an @{typ int} using the function |
366 change every @{typ nat} in a term into an @{typ int} using the function: |
391 *} |
367 *} |
392 |
368 |
393 ML{*fun nat_to_int t = |
369 ML{*fun nat_to_int t = |
394 (case t of |
370 (case t of |
395 @{typ nat} => @{typ int} |
371 @{typ nat} => @{typ int} |
396 | Type (s, ts) => Type (s, map nat_to_int ts) |
372 | Type (s, ts) => Type (s, map nat_to_int ts) |
397 | _ => t)*} |
373 | _ => t)*} |
398 |
374 |
399 text {* |
375 text {* |
400 an then apply it as follows: |
376 An example as follows: |
401 |
|
402 |
377 |
403 @{ML_response_fake [display,gray] |
378 @{ML_response_fake [display,gray] |
404 "map_types nat_to_int @{term \"a = (1::nat)\"}" |
379 "map_types nat_to_int @{term \"a = (1::nat)\"}" |
405 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\") |
380 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\") |
406 $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"} |
381 $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"} |
454 |
429 |
455 (FIXME: @{text "ctyp_of"}, @{ML fastype_of}, @{text dummyT}) |
430 (FIXME: @{text "ctyp_of"}, @{ML fastype_of}, @{text dummyT}) |
456 |
431 |
457 *} |
432 *} |
458 |
433 |
|
434 section {* Constants *} |
|
435 |
|
436 text {* |
|
437 There are a few subtle issues with constants. They usually crop up when |
|
438 pattern matching terms or constructing term. While it is perfectly ok |
|
439 to write the function @{text is_true} as follows |
|
440 *} |
|
441 |
|
442 ML{*fun is_true @{term True} = true |
|
443 | is_true _ = false*} |
|
444 |
|
445 text {* |
|
446 this does not work for picking out @{text "\<forall>"}-quantified terms. Because |
|
447 the function |
|
448 *} |
|
449 |
|
450 ML{*fun is_all (@{term All} $ _) = true |
|
451 | is_all _ = false*} |
|
452 |
|
453 text {* |
|
454 will not correctly match: |
|
455 |
|
456 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "false"} |
|
457 |
|
458 The problem is that the @{text "@term"}-antiquotation in the pattern |
|
459 fixes the type of @{term "All"} to be @{typ "('a \<Rightarrow> bool) \<Rightarrow> bool"} for |
|
460 an arbitrary, but fixed type @{typ "'a"}. A properly working alternative |
|
461 for this function is |
|
462 *} |
|
463 |
|
464 ML{*fun is_all (Const ("All", _) $ _) = true |
|
465 | is_all _ = false*} |
|
466 |
|
467 text {* |
|
468 because now |
|
469 |
|
470 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"} |
|
471 |
|
472 matches correctly. |
|
473 |
|
474 However there is still a problem: consider the function that attempts to |
|
475 pick out a @{text "Nil"}-term: |
|
476 *} |
|
477 |
|
478 ML{*fun is_nil (Const ("Nil", _)) = true |
|
479 | is_nil _ = false *} |
|
480 |
|
481 text {* |
|
482 Unfortunately, also this one does not return the expected result, since |
|
483 |
|
484 @{ML_response [display,gray] "is_nil @{term \"Nil\"}" "false"} |
|
485 |
|
486 The problem is that on the ML-level the name of constants is not |
|
487 immediately clear. If you look at |
|
488 |
|
489 @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"} |
|
490 |
|
491 the name of the constant depends on the theory in which the term constructor |
|
492 @{text "Nil"} is defined and also in which datatype. Even worse, some |
|
493 constants have an even more complex name involving type-classes. Consider |
|
494 for example |
|
495 |
|
496 @{ML_response [display,gray] "(@{term \"0::nat\"}, @{term \"op *\"})" |
|
497 "(Const (\"HOL.zero_class.zero\", \<dots>), |
|
498 Const (\"HOL.times_class.times\", \<dots>))"} |
|
499 |
|
500 While you could always use the complete name, for example |
|
501 @{ML "Const (\"List.list.Nil\", @{typ \"nat list\"})"}, for referring to or |
|
502 matching against @{text "Nil"}, this would make the code rather brittle. |
|
503 The reason is that the theory and the name of the datatype can easily change. |
|
504 To make the code more robust it is better to use the antiquotation |
|
505 @{text "@{const_name \<dots>}"}. With this antiquotation you can harness the |
|
506 variable parts of the constant's name. Therefore the functions for |
|
507 matching against constants should be written as follows. |
|
508 *} |
|
509 |
|
510 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true |
|
511 | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true |
|
512 | is_nil_or_all _ = false *} |
|
513 |
|
514 text {* |
|
515 Having said this, you also frequently have to calculate what the |
|
516 ``base'' name of a constant is. For this you can use the function |
|
517 @{ML Sign.base_name}. For example: |
|
518 |
|
519 (FIXME is there an example for that statement?) |
|
520 |
|
521 |
|
522 @{ML_response [display,gray] "Sign.base_name \"List.list.Nil\"" "\"Nil\""} |
|
523 |
|
524 (FIXME authentic syntax?) |
|
525 |
|
526 \begin{readmore} |
|
527 FIXME |
|
528 \end{readmore} |
|
529 *} |
|
530 |
|
531 |
459 section {* Theorems *} |
532 section {* Theorems *} |
460 |
533 |
461 text {* |
534 text {* |
462 Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} |
535 Just like @{ML_type cterm}s, theorems are abstract objects of type @{ML_type thm} |
463 that can only be built by going through interfaces. As a consequence, every proof |
536 that can only be build by going through interfaces. As a consequence, every proof |
464 in Isabelle is correct by construction. |
537 in Isabelle is correct by construction. |
465 |
538 |
466 (FIXME reference LCF-philosophy) |
539 (FIXME reference LCF-philosophy) |
467 |
540 |
468 To see theorems in ``action'', let us give a proof on the ML-level for the following |
541 To see theorems in ``action'', let us give a proof on the ML-level for the following |
583 |
656 |
584 ML{*fun str_of_thms ctxt thms = |
657 ML{*fun str_of_thms ctxt thms = |
585 commas (map (str_of_thm ctxt) thms)*} |
658 commas (map (str_of_thm ctxt) thms)*} |
586 |
659 |
587 |
660 |
588 section {* Operations on Constants (Names) *} |
|
589 |
|
590 text {* |
|
591 |
|
592 @{ML_response [display] "Sign.base_name \"List.list.Nil\"" "\"Nil\""} |
|
593 |
|
594 authentic syntax? |
|
595 |
|
596 *} |
|
597 |
|
598 ML {* @{const_name lfp} *} |
|
599 |
|
600 text {* |
|
601 constants in case-patterns? |
|
602 |
|
603 In the meantime, lfp has been moved to the Inductive theory, so it is |
|
604 no longer called Lfp.lfp. If a @{text "@{const_name}"} antiquotation had been |
|
605 used, we would have gotten an error for this. Another advantage of the |
|
606 antiquotation is that we can then just write @{text "@{const_name lfp}"} rather |
|
607 than @{text "@{const_name Lfp.lfp}"} or whatever, and it expands to the correct |
|
608 name. |
|
609 |
|
610 *} |
|
611 |
|
612 section {* Combinators\label{sec:combinators} *} |
661 section {* Combinators\label{sec:combinators} *} |
613 |
662 |
614 text {* |
663 text {* |
615 For beginners, perhaps the most puzzling parts in the existing code of Isabelle are |
664 For beginners, perhaps the most puzzling parts in the existing code of Isabelle are |
616 the combinators. At first they seem to greatly obstruct the |
665 the combinators. At first they seem to greatly obstruct the |