850 definition and many useful operations are implemented |
850 definition and many useful operations are implemented |
851 in @{ML_file "Pure/type.ML"}. |
851 in @{ML_file "Pure/type.ML"}. |
852 \end{readmore} |
852 \end{readmore} |
853 *} |
853 *} |
854 |
854 |
855 section {* Constructing Terms Manually\label{sec:terms_types_manually} *} |
855 section {* Constructing Terms and Types Manually\label{sec:terms_types_manually} *} |
856 |
856 |
857 text {* |
857 text {* |
858 While antiquotations are very convenient for constructing terms, they can |
858 While antiquotations are very convenient for constructing terms, they can |
859 only construct fixed terms (remember they are ``linked'' at compile-time). |
859 only construct fixed terms (remember they are ``linked'' at compile-time). |
860 However, you often need to construct terms dynamically. For example, a |
860 However, you often need to construct terms dynamically. For example, a |
902 and a list of terms as arguments, and produces as output the term |
902 and a list of terms as arguments, and produces as output the term |
903 list applied to the term. For example |
903 list applied to the term. For example |
904 |
904 |
905 @{ML_response_fake [display,gray] |
905 @{ML_response_fake [display,gray] |
906 "let |
906 "let |
907 val t = @{term \"P::nat\"} |
907 val trm = @{term \"P::nat\"} |
908 val args = [@{term \"True\"}, @{term \"False\"}] |
908 val args = [@{term \"True\"}, @{term \"False\"}] |
909 in |
909 in |
910 list_comb (t, args) |
910 list_comb (trm, args) |
911 end" |
911 end" |
912 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
912 "Free (\"P\", \"nat\") $ Const (\"True\", \"bool\") $ Const (\"False\", \"bool\")"} |
913 |
913 |
914 Another handy function is @{ML [index] lambda}, which abstracts a variable |
914 Another handy function is @{ML [index] lambda}, which abstracts a variable |
915 in a term. For example |
915 in a term. For example |
916 |
916 |
917 @{ML_response_fake [display,gray] |
917 @{ML_response_fake [display,gray] |
918 "lambda @{term \"x::nat\"} @{term \"(P::nat \<Rightarrow> bool) x\"}" |
918 "let |
|
919 val x_nat = @{term \"x::nat\"} |
|
920 val trm = @{term \"(P::nat \<Rightarrow> bool) x\"} |
|
921 in |
|
922 lambda x_nat trm |
|
923 end" |
919 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"} |
924 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Bound 0)"} |
920 |
925 |
921 In this example, @{ML lambda} produces a de Bruijn index (i.e.~@{ML "Bound 0"}), |
926 In this example, @{ML lambda} produces a de Bruijn index (i.e.~@{ML "Bound 0"}), |
922 and an abstraction. It also records the type of the abstracted |
927 and an abstraction. It also records the type of the abstracted |
923 variable and for printing purposes also its name. Note that because of the |
928 variable and for printing purposes also its name. Note that because of the |
924 typing annotation on @{text "P"}, the variable @{text "x"} in @{text "P x"} |
929 typing annotation on @{text "P"}, the variable @{text "x"} in @{text "P x"} |
925 is of the same type as the abstracted variable. If it is of different type, |
930 is of the same type as the abstracted variable. If it is of different type, |
926 as in |
931 as in |
927 |
932 |
928 @{ML_response_fake [display,gray] |
933 @{ML_response_fake [display,gray] |
929 "lambda @{term \"x::nat\"} @{term \"(P::bool \<Rightarrow> bool) x\"}" |
934 "let |
930 "Abs (\"x\", \"nat\", Free (\"P\", \"bool \<Rightarrow> bool\") $ Free (\"x\", \"bool\"))"} |
935 val x_int = @{term \"x::int\"} |
931 |
936 val trm = @{term \"(P::nat \<Rightarrow> bool) x\"} |
932 then the variable @{text "Free (\"x\", \"bool\")"} is \emph{not} abstracted. |
937 in |
|
938 lambda x_int trm |
|
939 end" |
|
940 "Abs (\"x\", \"int\", Free (\"P\", \"nat \<Rightarrow> bool\") $ Free (\"x\", \"nat\"))"} |
|
941 |
|
942 then the variable @{text "Free (\"x\", \"int\")"} is \emph{not} abstracted. |
933 This is a fundamental principle |
943 This is a fundamental principle |
934 of Church-style typing, where variables with the same name still differ, if they |
944 of Church-style typing, where variables with the same name still differ, if they |
935 have different type. |
945 have different type. |
936 |
946 |
937 There is also the function @{ML [index] subst_free} with which terms can |
947 There is also the function @{ML [index] subst_free} with which terms can |
941 |
951 |
942 @{ML_response_fake [display,gray] |
952 @{ML_response_fake [display,gray] |
943 "let |
953 "let |
944 val s1 = (@{term \"(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0\"}, @{term \"y::nat \<Rightarrow> nat\"}) |
954 val s1 = (@{term \"(f::nat \<Rightarrow> nat \<Rightarrow> nat) 0\"}, @{term \"y::nat \<Rightarrow> nat\"}) |
945 val s2 = (@{term \"x::nat\"}, @{term \"True\"}) |
955 val s2 = (@{term \"x::nat\"}, @{term \"True\"}) |
946 val trm = @{term \"((f::nat \<Rightarrow> nat \<Rightarrow> nat) 0) x\"} |
956 val trm = @{term \"((f::nat \<Rightarrow> nat \<Rightarrow> nat) 0) x\"} |
947 in |
957 in |
948 subst_free [s1, s2] trm |
958 subst_free [s1, s2] trm |
949 end" |
959 end" |
950 "Free (\"y\", \"nat \<Rightarrow> nat\") $ Const (\"True\", \"bool\")"} |
960 "Free (\"y\", \"nat \<Rightarrow> nat\") $ Const (\"True\", \"bool\")"} |
951 |
961 |
965 example @{ML [index] mk_eq in HOLogic} constructs an equality out of two terms. |
975 example @{ML [index] mk_eq in HOLogic} constructs an equality out of two terms. |
966 The types needed in this equality are calculated from the type of the |
976 The types needed in this equality are calculated from the type of the |
967 arguments. For example |
977 arguments. For example |
968 |
978 |
969 @{ML_response_fake [gray,display] |
979 @{ML_response_fake [gray,display] |
970 "writeln (Syntax.string_of_term @{context} |
980 "let |
971 (HOLogic.mk_eq (@{term \"True\"}, @{term \"False\"})))" |
981 val eq = HOLogic.mk_eq (@{term \"True\"}, @{term \"False\"}) |
|
982 in |
|
983 writeln (Syntax.string_of_term @{context} eq) |
|
984 end" |
972 "True = False"} |
985 "True = False"} |
973 *} |
986 *} |
974 |
987 |
975 text {* |
988 text {* |
976 \begin{readmore} |
989 \begin{readmore} |
977 Most of the HOL-specific operations on terms and types are defined |
990 Most of the HOL-specific operations on terms and types are defined |
978 in @{ML_file "HOL/Tools/hologic.ML"}. |
991 in @{ML_file "HOL/Tools/hologic.ML"}. |
979 \end{readmore} |
992 \end{readmore} |
980 *} |
993 |
981 |
994 When constructing terms manually, there are a few subtle issues with |
982 section {* Constants *} |
995 constants. They usually crop up when pattern matching terms or types, or |
983 |
996 when constructing them. While it is perfectly ok to write the function |
984 text {* |
997 @{text is_true} as follows |
985 There are a few subtle issues with constants. They usually crop up when |
|
986 pattern matching terms or types, or when constructing them. While it is perfectly ok |
|
987 to write the function @{text is_true} as follows |
|
988 *} |
998 *} |
989 |
999 |
990 ML{*fun is_true @{term True} = true |
1000 ML{*fun is_true @{term True} = true |
991 | is_true _ = false*} |
1001 | is_true _ = false*} |
992 |
1002 |
1164 that is they take, besides a term, also a list of type-variables as input. |
1170 that is they take, besides a term, also a list of type-variables as input. |
1165 So in order to obtain the list of type-variables of a term you have to |
1171 So in order to obtain the list of type-variables of a term you have to |
1166 call them as follows |
1172 call them as follows |
1167 |
1173 |
1168 @{ML_response [gray,display] |
1174 @{ML_response [gray,display] |
1169 "Term.add_tfrees @{term \"(a,b)\"} []" |
1175 "Term.add_tfrees @{term \"(a, b)\"} []" |
1170 "[(\"'b\", [\"HOL.type\"]), (\"'a\", [\"HOL.type\"])]"} |
1176 "[(\"'b\", [\"HOL.type\"]), (\"'a\", [\"HOL.type\"])]"} |
1171 |
1177 |
1172 The reason for this definition is that @{ML add_tfrees in Term} can |
1178 The reason for this definition is that @{ML add_tfrees in Term} can |
1173 be easily folded over a list of terms. Similarly for all functions |
1179 be easily folded over a list of terms. Similarly for all functions |
1174 named @{text "add_"}some\_name in @{ML_file "Pure/term.ML"}. |
1180 named @{text "add_*"} in @{ML_file "Pure/term.ML"}. |
1175 |
1181 |
1176 *} |
1182 *} |
1177 |
1183 |
1178 |
1184 |
1179 section {* Type-Checking\label{sec:typechecking} *} |
1185 section {* Type-Checking\label{sec:typechecking} *} |