572 @{ML_response_fake [display,gray] "@{thms conj_ac}" |
572 @{ML_response_fake [display,gray] "@{thms conj_ac}" |
573 "(?P \<and> ?Q) = (?Q \<and> ?P) |
573 "(?P \<and> ?Q) = (?Q \<and> ?P) |
574 (?P \<and> ?Q \<and> ?R) = (?Q \<and> ?P \<and> ?R) |
574 (?P \<and> ?Q \<and> ?R) = (?Q \<and> ?P \<and> ?R) |
575 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)"} |
575 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)"} |
576 |
576 |
577 You can also refer to the current simpset. To illustrate this we implement the |
577 The point of these antiquotations is that referring to theorems in this way |
578 function that extracts the theorem names stored in a simpset. |
578 makes your code independent from what theorems the user might have stored |
|
579 under this name (this becomes especially important when you deal with |
|
580 theorem lists; see Section \ref{sec:attributes}). |
|
581 |
|
582 You can also refer to the current simpset via an antiquotation. To illustrate |
|
583 this we implement the function that extracts the theorem names stored in a |
|
584 simpset. |
579 *} |
585 *} |
580 |
586 |
581 ML{*fun get_thm_names_from_ss simpset = |
587 ML{*fun get_thm_names_from_ss simpset = |
582 let |
588 let |
583 val {simps,...} = MetaSimplifier.dest_ss simpset |
589 val {simps,...} = MetaSimplifier.dest_ss simpset |
594 @{ML_response_fake [display,gray] |
600 @{ML_response_fake [display,gray] |
595 "get_thm_names_from_ss @{simpset}" |
601 "get_thm_names_from_ss @{simpset}" |
596 "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"} |
602 "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"} |
597 |
603 |
598 Again, this way of referencing simpsets makes you independent from additions |
604 Again, this way of referencing simpsets makes you independent from additions |
599 of lemmas to the simpset by the user that potentially cause loops. |
605 of lemmas to the simpset by the user that can potentially cause loops in your |
|
606 code. |
600 |
607 |
601 On the ML-level of Isabelle, you often have to work with qualified names. |
608 On the ML-level of Isabelle, you often have to work with qualified names. |
602 These are strings with some additional information, such as positional information |
609 These are strings with some additional information, such as positional information |
603 and qualifiers. Such qualified names can be generated with the antiquotation |
610 and qualifiers. Such qualified names can be generated with the antiquotation |
604 @{text "@{binding \<dots>}"}. |
611 @{text "@{binding \<dots>}"}. For example |
605 |
612 |
606 @{ML_response [display,gray] |
613 @{ML_response [display,gray] |
607 "@{binding \"name\"}" |
614 "@{binding \"name\"}" |
608 "name"} |
615 "name"} |
609 |
616 |
610 An example where a binding is needed is the function @{ML [index] define in |
617 An example where a qualified name is needed is the function |
611 LocalTheory}. This function is below used to define the constant @{term |
618 @{ML [index] define in LocalTheory}. This function is used below to define |
612 "TrueConj"} as the conjunction |
619 the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}. |
613 @{term "True \<and> True"}. |
|
614 *} |
620 *} |
615 |
621 |
616 local_setup %gray {* |
622 local_setup %gray {* |
617 snd o LocalTheory.define Thm.internalK |
623 snd o LocalTheory.define Thm.internalK |
618 ((@{binding "TrueConj"}, NoSyn), |
624 ((@{binding "TrueConj"}, NoSyn), |
628 |
634 |
629 (FIXME give a better example why bindings are important; maybe |
635 (FIXME give a better example why bindings are important; maybe |
630 give a pointer to \isacommand{local\_setup}; if not, then explain |
636 give a pointer to \isacommand{local\_setup}; if not, then explain |
631 why @{ML snd} is needed) |
637 why @{ML snd} is needed) |
632 |
638 |
633 While antiquotations have many applications, they were originally introduced |
639 It is also possible to define your own antiquotations. But you should |
634 in order to avoid explicit bindings of theorems such as: |
640 exercise care when introducing new one, as they can also make your |
635 *} |
641 code unreadable. In the next section we will see how the (build in) |
636 |
642 antiquotation @{text "@{term \<dots>}"} can be used to construct terms. |
637 ML{*val allI = thm "allI" *} |
643 A restriction of this antiquotation is that it does not allow you to |
638 |
644 use schematic variables. If you want a antiquotation that does not |
639 text {* |
645 have this restriction, you can implement your own using the |
640 Such bindings are difficult to maintain and can be overwritten by the |
646 function @{ML [index] ML_Antiquote.inline}. |
641 user accidentally. This often broke Isabelle |
647 *} |
642 packages. Antiquotations solve this problem, since they are ``linked'' |
648 |
643 statically at compile-time. However, this static linkage also limits their |
649 ML %linenosgray{*ML_Antiquote.inline "term_pat" |
644 usefulness in cases where data needs to be built up dynamically. In the |
|
645 course of this chapter you will learn more about antiquotations: |
|
646 they can simplify Isabelle programming since one can directly access all |
|
647 kinds of logical elements from the ML-level. |
|
648 *} |
|
649 |
|
650 text {* FIXME: give an example of a user defined antiquotation *} |
|
651 |
|
652 ML{*ML_Antiquote.inline "term_pat" |
|
653 (Args.context -- Scan.lift Args.name_source >> |
650 (Args.context -- Scan.lift Args.name_source >> |
654 (fn (ctxt, s) => |
651 (fn (ctxt, s) => |
655 s |> ProofContext.read_term_pattern ctxt |
652 s |> ProofContext.read_term_pattern ctxt |
656 |> ML_Syntax.print_term |
653 |> ML_Syntax.print_term |
657 |> ML_Syntax.atomic))*} |
654 |> ML_Syntax.atomic))*} |
658 |
655 |
659 ML{*@{term_pat "?x + ?y"}*} |
656 text {* |
660 |
657 We call the antiquotation @{text "term_pat"} (Line 1); the parser in Line |
661 text {* |
658 2 provides us with a context and a string; this string is transformed into a |
|
659 term using the function @{ML read_term_pattern in ProofContext} (Line 4); |
|
660 the next two lines print the term so that the ML-system can understand |
|
661 them. An example of this antiquotation is as follows. |
|
662 |
|
663 @{ML_response_fake [display,gray] |
|
664 "@{term_pat \"Suc (?x::nat)\"}" |
|
665 "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"} |
|
666 |
662 \begin{readmore} |
667 \begin{readmore} |
663 @{ML_file "Pure/ML/ml_antiquote.ML"} |
668 The file @{ML_file "Pure/ML/ml_antiquote.ML"} contains the the definitions |
|
669 for most antiquotations. |
664 \end{readmore} |
670 \end{readmore} |
|
671 |
|
672 Note also that in Isabelle there are two kinds of antiquotations, which have |
|
673 very different infrastructures. The first kind, described in this section, |
|
674 is sometimes called \emph{ML-antiquotations}. They are used to refer to |
|
675 entities (like terms, types etc) from Isabelle's logic layer inside ML-code. |
|
676 They are ``linked'' statically at compile-time, which limits sometimes |
|
677 their usefulness in cases where, for example, terms needs to be built up |
|
678 dynamically. |
|
679 |
|
680 The other kind of antiquotations are called \emph{document antiquotations}. |
|
681 They are used only in the text parts of Isabelle and help with printing logical |
|
682 entities inside \LaTeX-documents. In this Tutorial we are not interested |
|
683 in these antiquotations, except in Appendix \ref{rec:docantiquotations} where |
|
684 we show how to implement your own document antiquotations. |
665 *} |
685 *} |
666 |
686 |
667 section {* Terms and Types *} |
687 section {* Terms and Types *} |
668 |
688 |
669 text {* |
689 text {* |
876 |
896 |
877 Another handy function is @{ML [index] lambda}, which abstracts a variable |
897 Another handy function is @{ML [index] lambda}, which abstracts a variable |
878 in a term. For example |
898 in a term. For example |
879 |
899 |
880 @{ML_response_fake [display,gray] |
900 @{ML_response_fake [display,gray] |
881 "lambda @{term \"x::nat\"} @{term \"(P::nat\<Rightarrow>bool) x\"}" |
901 "lambda @{term \"x::nat\"} @{term \"(P::nat \<Rightarrow> bool) x\"}" |
882 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"} |
902 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"} |
883 |
903 |
884 In this example, @{ML lambda} produces a de Bruijn index (i.e.~@{ML "Bound 0"}), |
904 In this example, @{ML lambda} produces a de Bruijn index (i.e.~@{ML "Bound 0"}), |
885 and an abstraction. It also records the type of the abstracted |
905 and an abstraction. It also records the type of the abstracted |
886 variable and for printing purposes also its name. Note that because of the |
906 variable and for printing purposes also its name. Note that because of the |
887 typing annotation on @{text "P"}, the variable @{text "x"} in @{text "P x"} |
907 typing annotation on @{text "P"}, the variable @{text "x"} in @{text "P x"} |
888 is of the same type as the abstracted variable. If it is of different type, |
908 is of the same type as the abstracted variable. If it is of different type, |
889 as in |
909 as in |
890 |
910 |
891 @{ML_response_fake [display,gray] |
911 @{ML_response_fake [display,gray] |
892 "lambda @{term \"x::nat\"} @{term \"(P::bool\<Rightarrow>bool) x\"}" |
912 "lambda @{term \"x::nat\"} @{term \"(P::bool \<Rightarrow> bool) x\"}" |
893 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Free (\"x\", \"bool\"))"} |
913 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Free (\"x\", \"bool\"))"} |
894 |
914 |
895 then the variable @{text "Free (\"x\", \"bool\")"} is \emph{not} abstracted. |
915 then the variable @{text "Free (\"x\", \"bool\")"} is \emph{not} abstracted. |
896 This is a fundamental principle |
916 This is a fundamental principle |
897 of Church-style typing, where variables with the same name still differ, if they |
917 of Church-style typing, where variables with the same name still differ, if they |
898 have different type. |
918 have different type. |
899 |
919 |
900 There is also the function @{ML [index] subst_free} with which terms can |
920 There is also the function @{ML [index] subst_free} with which terms can |
901 be replaced by other terms. For example below, we will replace in |
921 be replaced by other terms. For example below, we will replace in |
902 @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0 x"} |
922 @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0 x"} |
903 the subterm @{term "(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0"} by @{term y}, and @{term x} by @{term True}. |
923 the subterm @{term "(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0"} by @{term y}, and @{term x} by @{term True}. |
904 |
924 |
905 @{ML_response_fake [display,gray] |
925 @{ML_response_fake [display,gray] |
906 "subst_free [(@{term \"(f::nat\<Rightarrow>nat\<Rightarrow>nat) 0\"}, @{term \"y::nat\<Rightarrow>nat\"}), |
926 "let |
907 (@{term \"x::nat\"}, @{term \"True\"})] |
927 val s1 = (@{term \"(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0\"}, @{term \"y::nat \<Rightarrow> nat\"}) |
908 @{term \"((f::nat\<Rightarrow>nat\<Rightarrow>nat) 0) x\"}" |
928 val s2 = (@{term \"x::nat\"}, @{term \"True\"}) |
|
929 val trm = @{term \"((f::nat \<Rightarrow> nat \<Rightarrow> nat) 0) x\"} |
|
930 in |
|
931 subst_free [s1, s2] trm |
|
932 end" |
909 "Free (\"y\", \"nat \<Rightarrow> nat\") $ Const (\"True\", \"bool\")"} |
933 "Free (\"y\", \"nat \<Rightarrow> nat\") $ Const (\"True\", \"bool\")"} |
910 |
934 |
911 As can be seen, @{ML subst_free} does not take typability into account. |
935 As can be seen, @{ML subst_free} does not take typability into account. |
912 However it takes alpha-equivalence into account: |
936 However it takes alpha-equivalence into account: |
913 |
937 |
914 @{ML_response_fake [display, gray] |
938 @{ML_response_fake [display, gray] |
915 "subst_free [(@{term \"(\<lambda>y::nat. y)\"}, @{term \"x::nat\"})] |
939 "let |
916 @{term \"(\<lambda>x::nat. x)\"}" |
940 val s = (@{term \"(\<lambda>y::nat. y)\"}, @{term \"x::nat\"}) |
|
941 val trm = @{term \"(\<lambda>x::nat. x)\"} |
|
942 in |
|
943 subst_free [s] trm |
|
944 end" |
917 "Free (\"x\", \"nat\")"} |
945 "Free (\"x\", \"nat\")"} |
918 |
946 |
919 There are many convenient functions that construct specific HOL-terms. For |
947 There are many convenient functions that construct specific HOL-terms. For |
920 example @{ML [index] mk_eq in HOLogic} constructs an equality out of two terms. |
948 example @{ML [index] mk_eq in HOLogic} constructs an equality out of two terms. |
921 The types needed in this equality are calculated from the type of the |
949 The types needed in this equality are calculated from the type of the |