169 |
169 |
170 |
170 |
171 section {* Combinators\label{sec:combinators} *} |
171 section {* Combinators\label{sec:combinators} *} |
172 |
172 |
173 text {* |
173 text {* |
174 For beginners, perhaps the most puzzling parts in the existing code of Isabelle are |
174 For beginners perhaps the most puzzling parts in the existing code of Isabelle are |
175 the combinators. At first they seem to greatly obstruct the |
175 the combinators. At first they seem to greatly obstruct the |
176 comprehension of the code, but after getting familiar with them, they |
176 comprehension of the code, but after getting familiar with them, they |
177 actually ease the understanding and also the programming. |
177 actually ease the understanding and also the programming. |
178 |
178 |
179 The simplest combinator is @{ML I}, which is just the identity function defined as |
179 The simplest combinator is @{ML I}, which is just the identity function defined as |
211 the first component of the pair (Line 4) and finally incrementing the first |
211 the first component of the pair (Line 4) and finally incrementing the first |
212 component by 4 (Line 5). This kind of cascading manipulations of values is quite |
212 component by 4 (Line 5). This kind of cascading manipulations of values is quite |
213 common when dealing with theories (for example by adding a definition, followed by |
213 common when dealing with theories (for example by adding a definition, followed by |
214 lemmas and so on). The reverse application allows you to read what happens in |
214 lemmas and so on). The reverse application allows you to read what happens in |
215 a top-down manner. This kind of coding should also be familiar, |
215 a top-down manner. This kind of coding should also be familiar, |
216 if you used Haskell's do-notation. Writing the function @{ML inc_by_five} using |
216 if you used to Haskell's do-notation. Writing the function @{ML inc_by_five} using |
217 the reverse application is much clearer than writing |
217 the reverse application is much clearer than writing |
218 *} |
218 *} |
219 |
219 |
220 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*} |
220 ML{*fun inc_by_five x = fst ((fn x => (x, x)) (x + 1)) + 4*} |
221 |
221 |
378 |
378 |
379 In a similar way you can use antiquotations to refer to proved theorems: |
379 In a similar way you can use antiquotations to refer to proved theorems: |
380 |
380 |
381 @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"} |
381 @{ML_response_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"} |
382 |
382 |
383 and current simpsets: |
383 and current simpsets. For this we use the function that extracts the |
384 |
384 theorem names stored in the simpset. |
385 @{ML_response_fake [display,gray] |
385 *} |
386 "let |
386 |
387 val ({rules,...}, _) = MetaSimplifier.rep_ss @{simpset} |
387 ML{*fun get_thm_names simpset = |
|
388 let |
|
389 val ({rules,...}, _) = MetaSimplifier.rep_ss simpset |
388 in |
390 in |
389 map #name (Net.entries rules) |
391 map #name (Net.entries rules) |
390 end" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"} |
392 end*} |
391 |
393 |
392 The code about simpsets extracts the theorem names stored in the |
394 text {* |
393 simpset. You can get hold of the current simpset with the antiquotation |
395 The function @{ML rep_ss in MetaSimplifier} returns a record containing all |
394 @{text "@{simpset}"}. The function @{ML rep_ss in MetaSimplifier} returns a record |
396 information about the simpset. The rules of a simpset are stored in a |
395 containing all information about the simpset. The rules of a simpset are |
397 \emph{discrimination net} (a data structure for fast indexing). From this |
396 stored in a \emph{discrimination net} (a data structure for fast |
398 net you can extract the entries using the function @{ML Net.entries}. |
397 indexing). From this net you can extract the entries using the function @{ML |
399 You can now use @{ML get_thm_names} to obtain all names of theorems of |
398 Net.entries}. |
400 the current simpset using the antiquotation @{text "@{simpset}"}.\footnote |
399 |
401 {FIXME: you cannot cleanly match against lists with ommited parts} |
|
402 |
|
403 @{ML_response_fake [display,gray] |
|
404 "get_thm_names @{simpset}" "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"} |
400 |
405 |
401 \begin{readmore} |
406 \begin{readmore} |
402 The infrastructure for simpsets is implemented in @{ML_file "Pure/meta_simplifier.ML"} |
407 The infrastructure for simpsets is implemented in @{ML_file "Pure/meta_simplifier.ML"} |
403 and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented |
408 and @{ML_file "Pure/simplifier.ML"}. Discrimination nets are implemented |
404 in @{ML_file "Pure/net.ML"}. |
409 in @{ML_file "Pure/net.ML"}. |
509 written as: |
514 written as: |
510 |
515 |
511 *} |
516 *} |
512 |
517 |
513 ML{*fun make_imp P Q tau = |
518 ML{*fun make_imp P Q tau = |
514 let |
519 let |
515 val x = Free ("x",tau) |
520 val x = Free ("x",tau) |
516 in |
521 in |
517 Logic.all x (Logic.mk_implies (P $ x, Q $ x)) |
522 Logic.all x (Logic.mk_implies (P $ x, Q $ x)) |
518 end *} |
523 end *} |
519 |
524 |
520 text {* |
525 text {* |
521 The reason is that you cannot pass the arguments @{term P}, @{term Q} and |
526 The reason is that you cannot pass the arguments @{term P}, @{term Q} and |
522 @{term "tau"} into an antiquotation. For example the following does \emph{not} work. |
527 @{term "tau"} into an antiquotation. For example the following does \emph{not} work. |
523 *} |
528 *} |
601 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\") |
606 "Const (\"op =\", \"int \<Rightarrow> int \<Rightarrow> bool\") |
602 $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"} |
607 $ Free (\"a\", \"int\") $ Const (\"HOL.one_class.one\", \"int\")"} |
603 |
608 |
604 |
609 |
605 There are a few subtle issues with constants. They usually crop up when |
610 There are a few subtle issues with constants. They usually crop up when |
606 pattern matching terms or constructing terms. While it is perfectly ok |
611 pattern matching terms or types, or constructing them. While it is perfectly ok |
607 to write the function @{text is_true} as follows |
612 to write the function @{text is_true} as follows |
608 *} |
613 *} |
609 |
614 |
610 ML{*fun is_true @{term True} = true |
615 ML{*fun is_true @{term True} = true |
611 | is_true _ = false*} |
616 | is_true _ = false*} |
635 text {* |
640 text {* |
636 because now |
641 because now |
637 |
642 |
638 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"} |
643 @{ML_response [display,gray] "is_all @{term \"\<forall>x::nat. P x\"}" "true"} |
639 |
644 |
640 matches correctly (the wildcard in the pattern matches any type). |
645 matches correctly (the first wildcard in the pattern matches any type). |
641 |
646 |
642 However there is still a problem: consider the similar function that |
647 However there is still a problem: consider the similar function that |
643 attempts to pick out a @{text "Nil"}-term: |
648 attempts to pick out @{text "Nil"}-terms: |
644 *} |
649 *} |
645 |
650 |
646 ML{*fun is_nil (Const ("Nil", _)) = true |
651 ML{*fun is_nil (Const ("Nil", _)) = true |
647 | is_nil _ = false *} |
652 | is_nil _ = false *} |
648 |
653 |
656 because @{term "All"} is such a fundamental constant, which can be referenced |
661 because @{term "All"} is such a fundamental constant, which can be referenced |
657 by @{ML "Const (\"All\", some_type)" for some_type}. However, if you look at |
662 by @{ML "Const (\"All\", some_type)" for some_type}. However, if you look at |
658 |
663 |
659 @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"} |
664 @{ML_response [display,gray] "@{term \"Nil\"}" "Const (\"List.list.Nil\", \<dots>)"} |
660 |
665 |
661 the name of the constant @{term "Nil"} depends on the theory in which the |
666 the name of the constant @{text "Nil"} depends on the theory in which the |
662 term constructor is defined (@{text "List"}) and also in which datatype |
667 term constructor is defined (@{text "List"}) and also in which datatype |
663 (@{text "list"}). Even worse, some constants have a name involving |
668 (@{text "list"}). Even worse, some constants have a name involving |
664 type-classes. Consider for example the constants for @{term "zero"} and |
669 type-classes. Consider for example the constants for @{term "zero"} and |
665 @{text "(op *)"}: |
670 \mbox{@{text "(op *)"}}: |
666 |
671 |
667 @{ML_response [display,gray] "(@{term \"0::nat\"}, @{term \"op *\"})" |
672 @{ML_response [display,gray] "(@{term \"0::nat\"}, @{term \"op *\"})" |
668 "(Const (\"HOL.zero_class.zero\", \<dots>), |
673 "(Const (\"HOL.zero_class.zero\", \<dots>), |
669 Const (\"HOL.times_class.times\", \<dots>))"} |
674 Const (\"HOL.times_class.times\", \<dots>))"} |
670 |
675 |
682 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true |
687 ML{*fun is_nil_or_all (Const (@{const_name "Nil"}, _)) = true |
683 | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true |
688 | is_nil_or_all (Const (@{const_name "All"}, _) $ _) = true |
684 | is_nil_or_all _ = false *} |
689 | is_nil_or_all _ = false *} |
685 |
690 |
686 text {* |
691 text {* |
687 Note that you occasional have to calculate what the ``base'' name of a given |
692 Occasional you have to calculate what the ``base'' name of a given |
688 constant is. For this you can use the function @{ML Sign.extern_const} or |
693 constant is. For this you can use the function @{ML Sign.extern_const} or |
689 @{ML Sign.base_name}. For example: |
694 @{ML Sign.base_name}. For example: |
690 |
695 |
691 @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""} |
696 @{ML_response [display,gray] "Sign.extern_const @{theory} \"List.list.Nil\"" "\"Nil\""} |
692 |
697 |
693 The difference between both functions is that @{ML extern_const in Sign} returns |
698 The difference between both functions is that @{ML extern_const in Sign} returns |
694 the smallest name that is still unique, whereas @{ML base_name in Sign} always |
699 the smallest name that is still unique, whereas @{ML base_name in Sign} always |
695 strips off all qualifiers. |
700 strips off all qualifiers. |
696 |
701 |
697 (FIXME authentic syntax on the ML-level) |
|
698 |
|
699 \begin{readmore} |
702 \begin{readmore} |
700 FIXME |
703 FIXME |
701 \end{readmore} |
704 \end{readmore} |
702 *} |
705 *} |
703 |
706 |
704 |
707 |
705 section {* Type-Checking *} |
708 section {* Type-Checking *} |
706 |
709 |
707 text {* |
710 text {* |
708 |
711 |
709 You can freely construct and manipulate @{ML_type "term"}s, since they are just |
712 You can freely construct and manipulate @{ML_type "term"}s and @{ML_type |
710 arbitrary unchecked trees. However, you eventually want to see if a |
713 typ}es, since they are just arbitrary unchecked trees. However, you |
711 term is well-formed, or type-checks, relative to a theory. |
714 eventually want to see if a term is well-formed, or type-checks, relative to |
712 Type-checking is done via the function @{ML cterm_of}, which converts |
715 a theory. Type-checking is done via the function @{ML cterm_of}, which |
713 a @{ML_type term} into a @{ML_type cterm}, a \emph{certified} term. |
716 converts a @{ML_type term} into a @{ML_type cterm}, a \emph{certified} |
714 Unlike @{ML_type term}s, which are just trees, @{ML_type |
717 term. Unlike @{ML_type term}s, which are just trees, @{ML_type "cterm"}s are |
715 "cterm"}s are abstract objects that are guaranteed to be |
718 abstract objects that are guaranteed to be type-correct, and they can only |
716 type-correct, and they can only be constructed via ``official |
719 be constructed via ``official interfaces''. |
717 interfaces''. |
720 |
718 |
721 |
719 Type-checking is always relative to a theory context. For now we use |
722 Type-checking is always relative to a theory context. For now we use |
720 the @{ML "@{theory}"} antiquotation to get hold of the current theory. |
723 the @{ML "@{theory}"} antiquotation to get hold of the current theory. |
721 For example you can write: |
724 For example you can write: |
722 |
725 |
763 @{ML_response_fake [display,gray] |
766 @{ML_response_fake [display,gray] |
764 "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" |
767 "type_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::int\"})" |
765 "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"} |
768 "*** Exception- TYPE (\"type_of: type mismatch in application\" \<dots>"} |
766 |
769 |
767 Since the complete traversal might sometimes be too costly and |
770 Since the complete traversal might sometimes be too costly and |
768 not necessary, there is also the function @{ML fastype_of} which |
771 not necessary, there is also the function @{ML fastype_of}, which |
769 returns the type of a term. |
772 returns the type of a term. |
770 |
773 |
771 @{ML_response [display,gray] |
774 @{ML_response [display,gray] |
772 "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"} |
775 "fastype_of (@{term \"f::nat \<Rightarrow> bool\"} $ @{term \"x::nat\"})" "bool"} |
773 |
776 |
796 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $ |
799 "Const (\"HOL.plus_class.plus\", \"nat \<Rightarrow> nat \<Rightarrow> nat\") $ |
797 Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"} |
800 Const (\"HOL.one_class.one\", \"nat\") $ Free (\"x\", \"nat\")"} |
798 |
801 |
799 Instead of giving explicitly the type for the constant @{text "plus"} and the free |
802 Instead of giving explicitly the type for the constant @{text "plus"} and the free |
800 variable @{text "x"}, the type-inference filled in the missing information. |
803 variable @{text "x"}, the type-inference filled in the missing information. |
801 |
|
802 |
804 |
803 \begin{readmore} |
805 \begin{readmore} |
804 See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading, |
806 See @{ML_file "Pure/Syntax/syntax.ML"} where more functions about reading, |
805 checking and pretty-printing of terms are defined. |
807 checking and pretty-printing of terms are defined. |
806 \end{readmore} |
808 \end{readmore} |