4 *) |
4 *) |
5 |
5 |
6 section \<open>Cartesian products\<close> |
6 section \<open>Cartesian products\<close> |
7 |
7 |
8 theory Product_Type |
8 theory Product_Type |
9 imports Typedef Inductive Fun |
9 imports Typedef Inductive Fun |
10 keywords "inductive_set" "coinductive_set" :: thy_decl |
10 keywords "inductive_set" "coinductive_set" :: thy_decl |
11 begin |
11 begin |
12 |
12 |
13 subsection \<open>@{typ bool} is a datatype\<close> |
13 subsection \<open>@{typ bool} is a datatype\<close> |
14 |
14 |
15 free_constructors (discs_sels) case_bool for True | False |
15 free_constructors (discs_sels) case_bool for True | False |
36 |
36 |
37 declare case_split [cases type: bool] |
37 declare case_split [cases type: bool] |
38 \<comment> "prefer plain propositional version" |
38 \<comment> "prefer plain propositional version" |
39 |
39 |
40 lemma [code]: "HOL.equal False P \<longleftrightarrow> \<not> P" |
40 lemma [code]: "HOL.equal False P \<longleftrightarrow> \<not> P" |
41 and [code]: "HOL.equal True P \<longleftrightarrow> P" |
41 and [code]: "HOL.equal True P \<longleftrightarrow> P" |
42 and [code]: "HOL.equal P False \<longleftrightarrow> \<not> P" |
42 and [code]: "HOL.equal P False \<longleftrightarrow> \<not> P" |
43 and [code]: "HOL.equal P True \<longleftrightarrow> P" |
43 and [code]: "HOL.equal P True \<longleftrightarrow> P" |
44 and [code nbe]: "HOL.equal P P \<longleftrightarrow> True" |
44 and [code nbe]: "HOL.equal P P \<longleftrightarrow> True" |
45 by (simp_all add: equal) |
45 by (simp_all add: equal) |
46 |
46 |
315 fun case_prod_guess_names_tr' T [Abs (x, _, Abs _)] = raise Match |
315 fun case_prod_guess_names_tr' T [Abs (x, _, Abs _)] = raise Match |
316 | case_prod_guess_names_tr' T [Abs (x, xT, t)] = |
316 | case_prod_guess_names_tr' T [Abs (x, xT, t)] = |
317 (case (head_of t) of |
317 (case (head_of t) of |
318 Const (@{const_syntax case_prod}, _) => raise Match |
318 Const (@{const_syntax case_prod}, _) => raise Match |
319 | _ => |
319 | _ => |
320 let |
320 let |
321 val (_ :: yT :: _) = binder_types (domain_type T) handle Bind => raise Match; |
321 val (_ :: yT :: _) = binder_types (domain_type T) handle Bind => raise Match; |
322 val (y, t') = Syntax_Trans.atomic_abs_tr' ("y", yT, incr_boundvars 1 t $ Bound 0); |
322 val (y, t') = Syntax_Trans.atomic_abs_tr' ("y", yT, incr_boundvars 1 t $ Bound 0); |
323 val (x', t'') = Syntax_Trans.atomic_abs_tr' (x, xT, t'); |
323 val (x', t'') = Syntax_Trans.atomic_abs_tr' (x, xT, t'); |
324 in |
324 in |
325 Syntax.const @{syntax_const "_abs"} $ |
325 Syntax.const @{syntax_const "_abs"} $ |
616 |
616 |
617 declare mem_case_prodI [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
617 declare mem_case_prodI [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
618 declare case_prodI2' [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
618 declare case_prodI2' [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
619 declare case_prodI2 [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
619 declare case_prodI2 [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
620 declare case_prodI [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
620 declare case_prodI [intro!] \<comment> \<open>postponed to maintain traditional declaration order!\<close> |
621 |
621 |
622 lemma mem_case_prodE [elim!]: |
622 lemma mem_case_prodE [elim!]: |
623 assumes "z \<in> case_prod c p" |
623 assumes "z \<in> case_prod c p" |
624 obtains x y where "p = (x, y)" and "z \<in> c x y" |
624 obtains x y where "p = (x, y)" and "z \<in> c x y" |
625 using assms by (rule case_prodE2) |
625 using assms by (rule case_prodE2) |
626 |
626 |
629 fun exists_p_split (Const (@{const_name case_prod},_) $ _ $ (Const (@{const_name Pair},_)$_$_)) = true |
629 fun exists_p_split (Const (@{const_name case_prod},_) $ _ $ (Const (@{const_name Pair},_)$_$_)) = true |
630 | exists_p_split (t $ u) = exists_p_split t orelse exists_p_split u |
630 | exists_p_split (t $ u) = exists_p_split t orelse exists_p_split u |
631 | exists_p_split (Abs (_, _, t)) = exists_p_split t |
631 | exists_p_split (Abs (_, _, t)) = exists_p_split t |
632 | exists_p_split _ = false; |
632 | exists_p_split _ = false; |
633 in |
633 in |
634 fun split_conv_tac ctxt = SUBGOAL (fn (t, i) => |
634 fun split_conv_tac ctxt = SUBGOAL (fn (t, i) => |
635 if exists_p_split t |
635 if exists_p_split t |
636 then safe_full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps @{thms case_prod_conv}) i |
636 then safe_full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps @{thms case_prod_conv}) i |
637 else no_tac); |
637 else no_tac); |
638 end; |
638 end; |
639 \<close> |
639 \<close> |
640 |
640 |
641 (* This prevents applications of splitE for already splitted arguments leading |
641 (* This prevents applications of splitE for already splitted arguments leading |
642 to quite time-consuming computations (in particular for nested tuples) *) |
642 to quite time-consuming computations (in particular for nested tuples) *) |
654 |
654 |
655 (* Do NOT make this a simp rule as it |
655 (* Do NOT make this a simp rule as it |
656 a) only helps in special situations |
656 a) only helps in special situations |
657 b) can lead to nontermination in the presence of split_def |
657 b) can lead to nontermination in the presence of split_def |
658 *) |
658 *) |
659 lemma split_comp_eq: |
659 lemma split_comp_eq: |
660 fixes f :: "'a \<Rightarrow> 'b \<Rightarrow> 'c" |
660 fixes f :: "'a \<Rightarrow> 'b \<Rightarrow> 'c" |
661 and g :: "'d \<Rightarrow> 'a" |
661 and g :: "'d \<Rightarrow> 'a" |
662 shows "(\<lambda>u. f (g (fst u)) (snd u)) = case_prod (\<lambda>x. f (g x))" |
662 shows "(\<lambda>u. f (g (fst u)) (snd u)) = case_prod (\<lambda>x. f (g x))" |
663 by (rule ext) auto |
663 by (rule ext) auto |
664 |
664 |
834 and cases: "\<And>x y. c = (f x, g y) \<Longrightarrow> (x, y) \<in> R \<Longrightarrow> P" |
834 and cases: "\<And>x y. c = (f x, g y) \<Longrightarrow> (x, y) \<in> R \<Longrightarrow> P" |
835 shows P |
835 shows P |
836 apply (rule major [THEN imageE]) |
836 apply (rule major [THEN imageE]) |
837 apply (case_tac x) |
837 apply (case_tac x) |
838 apply (rule cases) |
838 apply (rule cases) |
839 apply simp_all |
839 apply simp_all |
840 done |
840 done |
841 |
841 |
842 definition apfst :: "('a \<Rightarrow> 'c) \<Rightarrow> 'a \<times> 'b \<Rightarrow> 'c \<times> 'b" |
842 definition apfst :: "('a \<Rightarrow> 'c) \<Rightarrow> 'a \<times> 'b \<Rightarrow> 'c \<times> 'b" |
843 where "apfst f = map_prod f id" |
843 where "apfst f = map_prod f id" |
844 |
844 |
845 definition apsnd :: "('b \<Rightarrow> 'c) \<Rightarrow> 'a \<times> 'b \<Rightarrow> 'a \<times> 'c" |
845 definition apsnd :: "('b \<Rightarrow> 'c) \<Rightarrow> 'a \<times> 'b \<Rightarrow> 'a \<times> 'c" |
846 where "apsnd f = map_prod id f" |
846 where "apsnd f = map_prod id f" |
847 |
847 |
848 lemma apfst_conv [simp, code]: "apfst f (x, y) = (f x, y)" |
848 lemma apfst_conv [simp, code]: "apfst f (x, y) = (f x, y)" |
849 by (simp add: apfst_def) |
849 by (simp add: apfst_def) |
850 |
850 |
851 lemma apsnd_conv [simp, code]: "apsnd f (x, y) = (x, f y)" |
851 lemma apsnd_conv [simp, code]: "apsnd f (x, y) = (x, f y)" |
852 by (simp add: apsnd_def) |
852 by (simp add: apsnd_def) |
853 |
853 |
854 lemma fst_apfst [simp]: "fst (apfst f x) = f (fst x)" |
854 lemma fst_apfst [simp]: "fst (apfst f x) = f (fst x)" |
855 by (cases x) simp |
855 by (cases x) simp |
856 |
856 |
1027 by auto |
1027 by auto |
1028 |
1028 |
1029 lemma Collect_case_prod_mono: "A \<le> B \<Longrightarrow> Collect (case_prod A) \<subseteq> Collect (case_prod B)" |
1029 lemma Collect_case_prod_mono: "A \<le> B \<Longrightarrow> Collect (case_prod A) \<subseteq> Collect (case_prod B)" |
1030 by auto (auto elim!: le_funE) |
1030 by auto (auto elim!: le_funE) |
1031 |
1031 |
1032 lemma Collect_split_mono_strong: |
1032 lemma Collect_split_mono_strong: |
1033 "X = fst ` A \<Longrightarrow> Y = snd ` A \<Longrightarrow> \<forall>a\<in>X. \<forall>b \<in> Y. P a b \<longrightarrow> Q a b |
1033 "X = fst ` A \<Longrightarrow> Y = snd ` A \<Longrightarrow> \<forall>a\<in>X. \<forall>b \<in> Y. P a b \<longrightarrow> Q a b |
1034 \<Longrightarrow> A \<subseteq> Collect (case_prod P) \<Longrightarrow> A \<subseteq> Collect (case_prod Q)" |
1034 \<Longrightarrow> A \<subseteq> Collect (case_prod P) \<Longrightarrow> A \<subseteq> Collect (case_prod Q)" |
1035 by fastforce |
1035 by fastforce |
1036 |
1036 |
1037 lemma UN_Times_distrib: "(\<Union>(a, b)\<in>A \<times> B. E a \<times> F b) = UNION A E \<times> UNION B F" |
1037 lemma UN_Times_distrib: "(\<Union>(a, b)\<in>A \<times> B. E a \<times> F b) = UNION A E \<times> UNION B F" |
1038 \<comment> \<open>Suggested by Pierre Chartier\<close> |
1038 \<comment> \<open>Suggested by Pierre Chartier\<close> |
1039 by blast |
1039 by blast |
1040 |
1040 |
1041 lemma split_paired_Ball_Sigma [simp, no_atp]: "(\<forall>z\<in>Sigma A B. P z) \<longleftrightarrow> (\<forall>x\<in>A. \<forall>y\<in>B x. P (x, y))" |
1041 lemma split_paired_Ball_Sigma [simp, no_atp]: "(\<forall>z\<in>Sigma A B. P z) \<longleftrightarrow> (\<forall>x\<in>A. \<forall>y\<in>B x. P (x, y))" |
1149 using inj_on_apsnd[of f UNIV] by simp |
1149 using inj_on_apsnd[of f UNIV] by simp |
1150 |
1150 |
1151 context |
1151 context |
1152 begin |
1152 begin |
1153 |
1153 |
1154 qualified definition product :: "'a set \<Rightarrow> 'b set \<Rightarrow> ('a \<times> 'b) set" where |
1154 qualified definition product :: "'a set \<Rightarrow> 'b set \<Rightarrow> ('a \<times> 'b) set" |
1155 [code_abbrev]: "product A B = A \<times> B" |
1155 where [code_abbrev]: "product A B = A \<times> B" |
1156 |
1156 |
1157 lemma member_product: "x \<in> Product_Type.product A B \<longleftrightarrow> x \<in> A \<times> B" |
1157 lemma member_product: "x \<in> Product_Type.product A B \<longleftrightarrow> x \<in> A \<times> B" |
1158 by (simp add: product_def) |
1158 by (simp add: product_def) |
1159 |
1159 |
1160 end |
1160 end |
1161 |
1161 |
1162 text \<open>The following @{const map_prod} lemmas are due to Joachim Breitner:\<close> |
1162 text \<open>The following @{const map_prod} lemmas are due to Joachim Breitner:\<close> |
1163 |
1163 |
1164 lemma map_prod_inj_on: |
1164 lemma map_prod_inj_on: |
1165 assumes "inj_on f A" and "inj_on g B" |
1165 assumes "inj_on f A" |
|
1166 and "inj_on g B" |
1166 shows "inj_on (map_prod f g) (A \<times> B)" |
1167 shows "inj_on (map_prod f g) (A \<times> B)" |
1167 proof (rule inj_onI) |
1168 proof (rule inj_onI) |
1168 fix x :: "'a \<times> 'c" |
1169 fix x :: "'a \<times> 'c" |
1169 fix y :: "'a \<times> 'c" |
1170 fix y :: "'a \<times> 'c" |
1170 assume "x \<in> A \<times> B" |
1171 assume "x \<in> A \<times> B" |