changeset 441 | 520127b708e6 |
parent 440 | a0b280dd4bc7 |
child 446 | 4c32349b9875 |
440:a0b280dd4bc7 | 441:520127b708e6 |
---|---|
1 theory Essential |
1 theory Essential |
2 imports Base FirstSteps |
2 imports Base First_Steps |
3 begin |
3 begin |
4 |
4 |
5 (*<*) |
5 (*<*) |
6 setup{* |
6 setup{* |
7 open_file_with_prelude |
7 open_file_with_prelude |
8 "Essential_Code.thy" |
8 "Essential_Code.thy" |
9 ["theory Essential", "imports Base FirstSteps", "begin"] |
9 ["theory Essential", "imports Base First_Steps", "begin"] |
10 *} |
10 *} |
11 (*>*) |
11 (*>*) |
12 |
12 |
13 |
13 |
14 chapter {* Isabelle Essentials *} |
14 chapter {* Isabelle Essentials *} |
82 "let |
82 "let |
83 val v1 = Var ((\"x\", 3), @{typ bool}) |
83 val v1 = Var ((\"x\", 3), @{typ bool}) |
84 val v2 = Var ((\"x1\", 3), @{typ bool}) |
84 val v2 = Var ((\"x1\", 3), @{typ bool}) |
85 val v3 = Free (\"x\", @{typ bool}) |
85 val v3 = Free (\"x\", @{typ bool}) |
86 in |
86 in |
87 string_of_terms @{context} [v1, v2, v3] |
87 pretty_terms @{context} [v1, v2, v3] |
88 |> tracing |
88 |> pwriteln |
89 end" |
89 end" |
90 "?x3, ?x1.3, x"} |
90 "?x3, ?x1.3, x"} |
91 |
91 |
92 When constructing terms, you are usually concerned with free variables (as |
92 When constructing terms, you are usually concerned with free variables (as |
93 mentioned earlier, you cannot construct schematic variables using the |
93 mentioned earlier, you cannot construct schematic variables using the |
116 |
116 |
117 @{ML_response_fake [display,gray] |
117 @{ML_response_fake [display,gray] |
118 "let |
118 "let |
119 val omega = Free (\"x\", @{typ \"nat \<Rightarrow> nat\"}) $ Free (\"x\", @{typ nat}) |
119 val omega = Free (\"x\", @{typ \"nat \<Rightarrow> nat\"}) $ Free (\"x\", @{typ nat}) |
120 in |
120 in |
121 tracing (string_of_term @{context} omega) |
121 pwriteln (pretty_term @{context} omega) |
122 end" |
122 end" |
123 "x x"} |
123 "x x"} |
124 |
124 |
125 Sometimes the internal representation of terms can be surprisingly different |
125 Sometimes the internal representation of terms can be surprisingly different |
126 from what you see at the user-level, because the layers of |
126 from what you see at the user-level, because the layers of |
421 @{ML_response_fake [display, gray, linenos] |
421 @{ML_response_fake [display, gray, linenos] |
422 "let |
422 "let |
423 val (vrs, trm) = strip_alls @{term \"\<forall>x y. x = (y::bool)\"} |
423 val (vrs, trm) = strip_alls @{term \"\<forall>x y. x = (y::bool)\"} |
424 in |
424 in |
425 subst_bounds (rev vrs, trm) |
425 subst_bounds (rev vrs, trm) |
426 |> string_of_term @{context} |
426 |> pretty_term @{context} |
427 |> tracing |
427 |> pwriteln |
428 end" |
428 end" |
429 "x = y"} |
429 "x = y"} |
430 |
430 |
431 Note that in Line 4 we had to reverse the list of variables that @{ML |
431 Note that in Line 4 we had to reverse the list of variables that @{ML |
432 strip_alls} returned. The reason is that the head of the list the function |
432 strip_alls} returned. The reason is that the head of the list the function |
455 |
455 |
456 @{ML_response_fake [gray,display] |
456 @{ML_response_fake [gray,display] |
457 "let |
457 "let |
458 val eq = HOLogic.mk_eq (@{term \"True\"}, @{term \"False\"}) |
458 val eq = HOLogic.mk_eq (@{term \"True\"}, @{term \"False\"}) |
459 in |
459 in |
460 string_of_term @{context} eq |
460 eq |> pretty_term @{context} |
461 |> tracing |
461 |> pwriteln |
462 end" |
462 end" |
463 "True = False"} |
463 "True = False"} |
464 |
464 |
465 \begin{readmore} |
465 \begin{readmore} |
466 There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file |
466 There are many functions in @{ML_file "Pure/term.ML"}, @{ML_file |
711 \begin{figure}[t] |
711 \begin{figure}[t] |
712 \begin{minipage}{\textwidth} |
712 \begin{minipage}{\textwidth} |
713 \begin{isabelle}*} |
713 \begin{isabelle}*} |
714 ML{*fun pretty_helper aux env = |
714 ML{*fun pretty_helper aux env = |
715 env |> Vartab.dest |
715 env |> Vartab.dest |
716 |> map ((fn (s1, s2) => s1 ^ " := " ^ s2) o aux) |
716 |> map ((fn (s1, s2) => Pretty.block [s1, Pretty.str ";=", s2]) o aux) |
717 |> commas |
717 |> Pretty.commas |
718 |> enclose "[" "]" |
718 |> Pretty.enum "" "[" "]" |
719 |> tracing |
719 |> pwriteln |
720 |
720 |
721 fun pretty_tyenv ctxt tyenv = |
721 fun pretty_tyenv ctxt tyenv = |
722 let |
722 let |
723 fun get_typs (v, (s, T)) = (TVar (v, s), T) |
723 fun get_typs (v, (s, T)) = (TVar (v, s), T) |
724 val print = pairself (Syntax.string_of_typ ctxt) |
724 val print = pairself (pretty_typ ctxt) |
725 in |
725 in |
726 pretty_helper (print o get_typs) tyenv |
726 pretty_helper (print o get_typs) tyenv |
727 end*} |
727 end*} |
728 text_raw {* |
728 text_raw {* |
729 \end{isabelle} |
729 \end{isabelle} |
899 *} |
899 *} |
900 |
900 |
901 ML{*fun pretty_env ctxt env = |
901 ML{*fun pretty_env ctxt env = |
902 let |
902 let |
903 fun get_trms (v, (T, t)) = (Var (v, T), t) |
903 fun get_trms (v, (T, t)) = (Var (v, T), t) |
904 val print = pairself (string_of_term ctxt) |
904 val print = pairself (pretty_term ctxt) |
905 in |
905 in |
906 pretty_helper (print o get_trms) env |
906 pretty_helper (print o get_trms) env |
907 end*} |
907 end*} |
908 |
908 |
909 text {* |
909 text {* |
940 @{ML_response_fake [display, gray] |
940 @{ML_response_fake [display, gray] |
941 "let |
941 "let |
942 val trm = @{term_pat \"(?X::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool) ?Y\"} |
942 val trm = @{term_pat \"(?X::(nat\<Rightarrow>nat\<Rightarrow>nat)\<Rightarrow>bool) ?Y\"} |
943 in |
943 in |
944 Envir.subst_term (Vartab.empty, fo_env) trm |
944 Envir.subst_term (Vartab.empty, fo_env) trm |
945 |> string_of_term @{context} |
945 |> pretty_term @{context} |
946 |> tracing |
946 |> pwriteln |
947 end" |
947 end" |
948 "P (\<lambda>a b. Q b a)"} |
948 "P (\<lambda>a b. Q b a)"} |
949 |
949 |
950 First-order matching is useful for matching against applications and |
950 First-order matching is useful for matching against applications and |
951 variables. It can also deal with abstractions and a limited form of |
951 variables. It can also deal with abstractions and a limited form of |
1022 "Envir.term_env"} pulls out the term environment from the result record. The |
1022 "Envir.term_env"} pulls out the term environment from the result record. The |
1023 corresponding function for type environment is @{ML_ind |
1023 corresponding function for type environment is @{ML_ind |
1024 "Envir.type_env"}. An assumption of this function is that the terms to be |
1024 "Envir.type_env"}. An assumption of this function is that the terms to be |
1025 unified have already the same type. In case of failure, the exceptions that |
1025 unified have already the same type. In case of failure, the exceptions that |
1026 are raised are either @{text Pattern}, @{text MATCH} or @{text Unif}. |
1026 are raised are either @{text Pattern}, @{text MATCH} or @{text Unif}. |
1027 *} |
|
1028 |
|
1029 (* |
|
1030 ML {* |
|
1031 fun patunif_in_emptyenv (t, u) = |
|
1032 let |
|
1033 val init = Envir.empty 0; |
|
1034 val env = Pattern.unify @{theory} (t, u) init; |
|
1035 in |
|
1036 (env |> Envir.term_env |> Vartab.dest, |
|
1037 env |> Envir.type_env |> Vartab.dest) |
|
1038 end |
|
1039 *} |
|
1040 |
|
1041 text {* |
|
1042 @{ML_response [display, gray] |
|
1043 "val t1 = @{term_pat \"(% x y. ?f y x)\"}; |
|
1044 val u1 = @{term_pat \"z::bool\"}; |
|
1045 (* type conflict isnt noticed *) |
|
1046 patunif_in_emptyenv (t1, u1);" |
|
1047 "check missing" |
|
1048 *} |
|
1049 @{ML_response [display, gray] |
|
1050 "val t2 = @{term_pat \"(% y. ?f y)\"} |> Term.strip_abs_body; |
|
1051 val u2 = @{term_pat \"z::bool\"}; |
|
1052 (* fails because of loose bounds *) |
|
1053 (* patunif_in_emptyenv (t2, u2) *)" |
|
1054 "check missing" |
|
1055 *} |
|
1056 @{ML_response [display, gray] |
|
1057 "val t3 = @{term_pat \"(% y. plu (?f y) (% x. g x))\"}; |
|
1058 val u3 = @{term_pat \"(% y. plu y (% x. g x))\"}; |
|
1059 (* eta redexe im term egal, hidden polym wird inst *) |
|
1060 patunif_in_emptyenv (t3, u3)" |
|
1061 "check missing" |
|
1062 *} |
|
1063 @{ML_response [display, gray] |
|
1064 "val t4 = @{term_pat \"(% y. plu (?f y) ((% x. g x) k))\"}; |
|
1065 val u4 = @{term_pat \"(% y. plu y ((% x. g x) k))\"}; |
|
1066 (* beta redexe are largely ignored, hidden polymorphism is instantiated *) |
|
1067 patunif_in_emptyenv (t4, u4)" |
|
1068 "check missing" |
|
1069 *} |
|
1070 @{ML_response [display, gray] |
|
1071 "val t5 = @{term_pat \"(% y. plu ((% x. ?f) y) ((% x. g x) k))\"}; |
|
1072 val u5 = @{term_pat \"(% y. plu y ((% x. g x) k))\"}; |
|
1073 (* fails: can't have beta redexes which seperate a var from its arguments *) |
|
1074 (* patunif_in_emptyenv (t5, u5) *)" |
|
1075 *} |
|
1076 |
|
1077 @{ML_response [display, gray] |
|
1078 "val t6 = @{term_pat \"(% x y. ?f x y) a b\"}; |
|
1079 val u6 = @{term_pat \"c\"}; |
|
1080 (* Pattern.pattern assumes argument is beta-normal *) |
|
1081 Pattern.pattern t6; |
|
1082 (* fails: can't have beta redexes which seperate a var from its arguments, |
|
1083 otherwise this would be general unification for general a,b,c *) |
|
1084 (* patunif_in_emptyenv (t6, u6) *)" |
|
1085 *} |
|
1086 @{ML_response [display, gray] |
|
1087 "val t7 = @{term_pat \"(% y. plu ((% x. ?f x) y) ((% x. g x) k))\"}; |
|
1088 val u7 = @{term_pat \"(% y. plu y ((% x. g x) k))\"}; |
|
1089 (* eta redexe die Pattern trennen brauchen nicht normalisiert sein *) |
|
1090 patunif_in_emptyenv (t7, u7)" |
|
1091 *} |
|
1092 @{ML_response [display, gray] |
|
1093 "val t8 = @{term_pat \"(% y. ?f y)\"}; |
|
1094 val u8 = @{term_pat \"(% y. y ?f)\"}; |
|
1095 (* variables of the same name are identified *) |
|
1096 (* patunif_in_emptyenv (t8, u8) *)" |
|
1097 *} |
|
1098 |
|
1099 @{ML_response [display, gray] |
|
1100 "val t9 = @{term_pat \"(% y. ?f y)\"}; |
|
1101 val u9 = @{term_pat \"(% y. ?f y)\"}; |
|
1102 (* trivial solutions are empty and don't contain ?f = ?f etc *) |
|
1103 patunif_in_emptyenv (t9, u9)" |
|
1104 *} |
|
1105 @{ML_response [display, gray] |
|
1106 "val t10 = @{term_pat \"(% y. (% x. ?f x) y)\"}; |
|
1107 val u10 = @{term_pat \"(% y. ?f y)\"}; |
|
1108 (* trivial solutions are empty and don't contain ?f = ?f etc *) |
|
1109 patunif_in_emptyenv (t10, u10)" |
|
1110 *} |
|
1111 @{ML_response [display, gray] |
|
1112 "val t11 = @{term_pat \"(% z. ?f z)\"}; |
|
1113 val u11 = @{term_pat \"(% z. k (?f z))\"}; |
|
1114 (* fails: occurs check *) |
|
1115 (* patunif_in_emptyenv (t11, u11) *)" |
|
1116 *} |
|
1117 @{ML_response [display, gray] |
|
1118 "val t12 = @{term_pat \"(% z. ?f z)\"}; |
|
1119 val u12 = @{term_pat \"?g a\"}; |
|
1120 (* fails: *both* terme have to be higher-order patterns *) |
|
1121 (* patunif_in_emptyenv (t12, u12) *)" |
|
1122 *} |
|
1123 *} |
|
1124 *) |
|
1125 |
|
1126 text {* |
|
1127 |
1027 |
1128 As mentioned before, unrestricted higher-order unification, respectively |
1028 As mentioned before, unrestricted higher-order unification, respectively |
1129 unrestricted higher-order matching, is in general undecidable and might also |
1029 unrestricted higher-order matching, is in general undecidable and might also |
1130 not posses a single most general solution. Therefore Isabelle implements the |
1030 not posses a single most general solution. Therefore Isabelle implements the |
1131 unification function @{ML_ind unifiers in Unify} so that it returns a lazy |
1031 unification function @{ML_ind unifiers in Unify} so that it returns a lazy |
1717 @{ML_response_fake [display,gray] |
1617 @{ML_response_fake [display,gray] |
1718 "let |
1618 "let |
1719 val eq = @{thm True_def} |
1619 val eq = @{thm True_def} |
1720 in |
1620 in |
1721 (Thm.lhs_of eq, Thm.rhs_of eq) |
1621 (Thm.lhs_of eq, Thm.rhs_of eq) |
1722 |> pairself (string_of_cterm @{context}) |
1622 |> pairself (Pretty.string_of o (pretty_cterm @{context})) |
1723 end" |
1623 end" |
1724 "(True, (\<lambda>x. x) = (\<lambda>x. x))"} |
1624 "(True, (\<lambda>x. x) = (\<lambda>x. x))"} |
1725 |
1625 |
1726 Other function produce terms that can be pattern-matched. |
1626 Other function produce terms that can be pattern-matched. |
1727 Suppose the following two theorems. |
1627 Suppose the following two theorems. |
1736 |
1636 |
1737 @{ML_response_fake [display,gray] |
1637 @{ML_response_fake [display,gray] |
1738 "let |
1638 "let |
1739 val ctxt = @{context} |
1639 val ctxt = @{context} |
1740 fun prems_and_concl thm = |
1640 fun prems_and_concl thm = |
1741 [\"Premises: \" ^ (string_of_terms ctxt (Thm.prems_of thm))] @ |
1641 [[Pretty.str \"Premises:\", pretty_terms ctxt (Thm.prems_of thm)], |
1742 [\"Conclusion: \" ^ (string_of_term ctxt (Thm.concl_of thm))] |
1642 [Pretty.str \"Conclusion:\", pretty_term ctxt (Thm.concl_of thm)]] |
1743 |> cat_lines |
1643 |> map Pretty.block |
1744 |> tracing |
1644 |> Pretty.chunks |
1645 |> pwriteln |
|
1745 in |
1646 in |
1746 prems_and_concl @{thm foo_test1}; |
1647 prems_and_concl @{thm foo_test1}; |
1747 prems_and_concl @{thm foo_test2} |
1648 prems_and_concl @{thm foo_test2} |
1748 end" |
1649 end" |
1749 "Premises: ?A, ?B |
1650 "Premises: ?A, ?B |