src/HOL/Product_Type.thy
changeset 63575 b9bd9e61fd63
parent 63566 e5abbdee461a
child 66251 cd935b7cb3fb
equal deleted inserted replaced
63574:4ea48cbc54c1 63575:b9bd9e61fd63
     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"