diff -r d71cdd1171c3 -r 01081bca31b6 src/HOL/Library/Sublist.thy --- a/src/HOL/Library/Sublist.thy Wed Aug 29 11:05:44 2012 +0900 +++ b/src/HOL/Library/Sublist.thy Wed Aug 29 12:23:14 2012 +0900 @@ -10,99 +10,94 @@ subsection {* Prefix order on lists *} -instantiation list :: (type) "{order, bot}" -begin +definition prefixeq :: "'a list => 'a list => bool" where + "prefixeq xs ys \ (\zs. ys = xs @ zs)" -definition - prefixeq_def: "xs \ ys \ (\zs. ys = xs @ zs)" - -definition - prefix_def: "xs < ys \ xs \ ys \ xs \ (ys::'a list)" +definition prefix :: "'a list => 'a list => bool" where + "prefix xs ys \ prefixeq xs ys \ xs \ ys" -definition - "bot = []" +interpretation prefix_order: order prefixeq prefix + by default (auto simp: prefixeq_def prefix_def) -instance proof -qed (auto simp add: prefixeq_def prefix_def bot_list_def) +interpretation prefix_bot: bot prefixeq prefix Nil + by default (simp add: prefixeq_def) -end - -lemma prefixeqI [intro?]: "ys = xs @ zs ==> xs \ ys" +lemma prefixeqI [intro?]: "ys = xs @ zs ==> prefixeq xs ys" unfolding prefixeq_def by blast lemma prefixeqE [elim?]: - assumes "xs \ ys" + assumes "prefixeq xs ys" obtains zs where "ys = xs @ zs" using assms unfolding prefixeq_def by blast -lemma prefixI' [intro?]: "ys = xs @ z # zs ==> xs < ys" +lemma prefixI' [intro?]: "ys = xs @ z # zs ==> prefix xs ys" unfolding prefix_def prefixeq_def by blast lemma prefixE' [elim?]: - assumes "xs < ys" + assumes "prefix xs ys" obtains z zs where "ys = xs @ z # zs" proof - - from `xs < ys` obtain us where "ys = xs @ us" and "xs \ ys" + from `prefix xs ys` obtain us where "ys = xs @ us" and "xs \ ys" unfolding prefix_def prefixeq_def by blast with that show ?thesis by (auto simp add: neq_Nil_conv) qed -lemma prefixI [intro?]: "xs \ ys ==> xs \ ys ==> xs < (ys::'a list)" +lemma prefixI [intro?]: "prefixeq xs ys ==> xs \ ys ==> prefix xs ys" unfolding prefix_def by blast lemma prefixE [elim?]: fixes xs ys :: "'a list" - assumes "xs < ys" - obtains "xs \ ys" and "xs \ ys" + assumes "prefix xs ys" + obtains "prefixeq xs ys" and "xs \ ys" using assms unfolding prefix_def by blast subsection {* Basic properties of prefixes *} -theorem Nil_prefixeq [iff]: "[] \ xs" +theorem Nil_prefixeq [iff]: "prefixeq [] xs" by (simp add: prefixeq_def) -theorem prefixeq_Nil [simp]: "(xs \ []) = (xs = [])" +theorem prefixeq_Nil [simp]: "(prefixeq xs []) = (xs = [])" by (induct xs) (simp_all add: prefixeq_def) -lemma prefixeq_snoc [simp]: "(xs \ ys @ [y]) = (xs = ys @ [y] \ xs \ ys)" +lemma prefixeq_snoc [simp]: "prefixeq xs (ys @ [y]) \ xs = ys @ [y] \ prefixeq xs ys" proof - assume "xs \ ys @ [y]" + assume "prefixeq xs (ys @ [y])" then obtain zs where zs: "ys @ [y] = xs @ zs" .. - show "xs = ys @ [y] \ xs \ ys" + show "xs = ys @ [y] \ prefixeq xs ys" by (metis append_Nil2 butlast_append butlast_snoc prefixeqI zs) next - assume "xs = ys @ [y] \ xs \ ys" - then show "xs \ ys @ [y]" - by (metis order_eq_iff order_trans prefixeqI) + assume "xs = ys @ [y] \ prefixeq xs ys" + then show "prefixeq xs (ys @ [y])" + by (metis prefix_order.eq_iff prefix_order.order_trans prefixeqI) qed -lemma Cons_prefixeq_Cons [simp]: "(x # xs \ y # ys) = (x = y \ xs \ ys)" +lemma Cons_prefixeq_Cons [simp]: "prefixeq (x # xs) (y # ys) = (x = y \ prefixeq xs ys)" by (auto simp add: prefixeq_def) -lemma less_eq_list_code [code]: - "([]\'a\{equal, ord} list) \ xs \ True" - "(x\'a\{equal, ord}) # xs \ [] \ False" - "(x\'a\{equal, ord}) # xs \ y # ys \ x = y \ xs \ ys" +lemma prefixeq_code [code]: + "prefixeq [] xs \ True" + "prefixeq (x # xs) [] \ False" + "prefixeq (x # xs) (y # ys) \ x = y \ prefixeq xs ys" by simp_all -lemma same_prefixeq_prefixeq [simp]: "(xs @ ys \ xs @ zs) = (ys \ zs)" +lemma same_prefixeq_prefixeq [simp]: "prefixeq (xs @ ys) (xs @ zs) = prefixeq ys zs" by (induct xs) simp_all -lemma same_prefixeq_nil [iff]: "(xs @ ys \ xs) = (ys = [])" - by (metis append_Nil2 append_self_conv order_eq_iff prefixeqI) +lemma same_prefixeq_nil [iff]: "prefixeq (xs @ ys) xs = (ys = [])" + by (metis append_Nil2 append_self_conv prefix_order.eq_iff prefixeqI) -lemma prefixeq_prefixeq [simp]: "xs \ ys ==> xs \ ys @ zs" - by (metis order_le_less_trans prefixeqI prefixE prefixI) +lemma prefixeq_prefixeq [simp]: "prefixeq xs ys ==> prefixeq xs (ys @ zs)" + by (metis prefix_order.le_less_trans prefixeqI prefixE prefixI) -lemma append_prefixeqD: "xs @ ys \ zs \ xs \ zs" +lemma append_prefixeqD: "prefixeq (xs @ ys) zs \ prefixeq xs zs" by (auto simp add: prefixeq_def) -theorem prefixeq_Cons: "(xs \ y # ys) = (xs = [] \ (\zs. xs = y # zs \ zs \ ys))" +theorem prefixeq_Cons: "prefixeq xs (y # ys) = (xs = [] \ (\zs. xs = y # zs \ prefixeq zs ys))" by (cases xs) (auto simp add: prefixeq_def) theorem prefixeq_append: - "(xs \ ys @ zs) = (xs \ ys \ (\us. xs = ys @ us \ us \ zs))" + "prefixeq xs (ys @ zs) = (prefixeq xs ys \ (\us. xs = ys @ us \ prefixeq us zs))" apply (induct zs rule: rev_induct) apply force apply (simp del: append_assoc add: append_assoc [symmetric]) @@ -110,47 +105,47 @@ done lemma append_one_prefixeq: - "xs \ ys ==> length xs < length ys ==> xs @ [ys ! length xs] \ ys" + "prefixeq xs ys ==> length xs < length ys ==> prefixeq (xs @ [ys ! length xs]) ys" unfolding prefixeq_def by (metis Cons_eq_appendI append_eq_appendI append_eq_conv_conj eq_Nil_appendI nth_drop') -theorem prefixeq_length_le: "xs \ ys ==> length xs \ length ys" +theorem prefixeq_length_le: "prefixeq xs ys ==> length xs \ length ys" by (auto simp add: prefixeq_def) lemma prefixeq_same_cases: - "(xs\<^isub>1::'a list) \ ys \ xs\<^isub>2 \ ys \ xs\<^isub>1 \ xs\<^isub>2 \ xs\<^isub>2 \ xs\<^isub>1" + "prefixeq (xs\<^isub>1::'a list) ys \ prefixeq xs\<^isub>2 ys \ prefixeq xs\<^isub>1 xs\<^isub>2 \ prefixeq xs\<^isub>2 xs\<^isub>1" unfolding prefixeq_def by (metis append_eq_append_conv2) -lemma set_mono_prefixeq: "xs \ ys \ set xs \ set ys" +lemma set_mono_prefixeq: "prefixeq xs ys \ set xs \ set ys" by (auto simp add: prefixeq_def) -lemma take_is_prefixeq: "take n xs \ xs" +lemma take_is_prefixeq: "prefixeq (take n xs) xs" unfolding prefixeq_def by (metis append_take_drop_id) -lemma map_prefixeqI: "xs \ ys \ map f xs \ map f ys" +lemma map_prefixeqI: "prefixeq xs ys \ prefixeq (map f xs) (map f ys)" by (auto simp: prefixeq_def) -lemma prefixeq_length_less: "xs < ys \ length xs < length ys" +lemma prefixeq_length_less: "prefix xs ys \ length xs < length ys" by (auto simp: prefix_def prefixeq_def) lemma prefix_simps [simp, code]: - "xs < [] \ False" - "[] < x # xs \ True" - "x # xs < y # ys \ x = y \ xs < ys" + "prefix xs [] \ False" + "prefix [] (x # xs) \ True" + "prefix (x # xs) (y # ys) \ x = y \ prefix xs ys" by (simp_all add: prefix_def cong: conj_cong) -lemma take_prefix: "xs < ys \ take n xs < ys" +lemma take_prefix: "prefix xs ys \ prefix (take n xs) ys" apply (induct n arbitrary: xs ys) apply (case_tac ys, simp_all)[1] - apply (metis order_less_trans prefixI take_is_prefixeq) + apply (metis prefix_order.less_trans prefixI take_is_prefixeq) done lemma not_prefixeq_cases: - assumes pfx: "\ ps \ ls" + assumes pfx: "\ prefixeq ps ls" obtains (c1) "ps \ []" and "ls = []" - | (c2) a as x xs where "ps = a#as" and "ls = x#xs" and "x = a" and "\ as \ xs" + | (c2) a as x xs where "ps = a#as" and "ls = x#xs" and "x = a" and "\ prefixeq as xs" | (c3) a as x xs where "ps = a#as" and "ls = x#xs" and "x \ a" proof (cases ps) case Nil then show ?thesis using pfx by simp @@ -165,7 +160,7 @@ show ?thesis proof (cases "x = a") case True - have "\ as \ xs" using pfx c Cons True by simp + have "\ prefixeq as xs" using pfx c Cons True by simp with c Cons True show ?thesis by (rule c2) next case False @@ -175,17 +170,17 @@ qed lemma not_prefixeq_induct [consumes 1, case_names Nil Neq Eq]: - assumes np: "\ ps \ ls" + assumes np: "\ prefixeq ps ls" and base: "\x xs. P (x#xs) []" and r1: "\x xs y ys. x \ y \ P (x#xs) (y#ys)" - and r2: "\x xs y ys. \ x = y; \ xs \ ys; P xs ys \ \ P (x#xs) (y#ys)" + and r2: "\x xs y ys. \ x = y; \ prefixeq xs ys; P xs ys \ \ P (x#xs) (y#ys)" shows "P ps ls" using np proof (induct ls arbitrary: ps) case Nil then show ?case by (auto simp: neq_Nil_conv elim!: not_prefixeq_cases intro!: base) next case (Cons y ys) - then have npfx: "\ ps \ (y # ys)" by simp + then have npfx: "\ prefixeq ps (y # ys)" by simp then obtain x xs where pv: "ps = x # xs" by (rule not_prefixeq_cases) auto show ?case by (metis Cons.hyps Cons_prefixeq_Cons npfx pv r1 r2) @@ -196,18 +191,18 @@ definition parallel :: "'a list => 'a list => bool" (infixl "\" 50) where - "(xs \ ys) = (\ xs \ ys \ \ ys \ xs)" + "(xs \ ys) = (\ prefixeq xs ys \ \ prefixeq ys xs)" -lemma parallelI [intro]: "\ xs \ ys ==> \ ys \ xs ==> xs \ ys" +lemma parallelI [intro]: "\ prefixeq xs ys ==> \ prefixeq ys xs ==> xs \ ys" unfolding parallel_def by blast lemma parallelE [elim]: assumes "xs \ ys" - obtains "\ xs \ ys \ \ ys \ xs" + obtains "\ prefixeq xs ys \ \ prefixeq ys xs" using assms unfolding parallel_def by blast theorem prefixeq_cases: - obtains "xs \ ys" | "ys < xs" | "xs \ ys" + obtains "prefixeq xs ys" | "prefix ys xs" | "xs \ ys" unfolding parallel_def prefix_def by blast theorem parallel_decomp: @@ -220,7 +215,7 @@ case (snoc x xs) show ?case proof (rule prefixeq_cases) - assume le: "xs \ ys" + assume le: "prefixeq xs ys" then obtain ys' where ys: "ys = xs @ ys'" .. show ?thesis proof (cases ys') @@ -233,7 +228,7 @@ same_prefixeq_prefixeq snoc.prems ys) qed next - assume "ys < xs" then have "ys \ xs @ [x]" by (simp add: prefix_def) + assume "prefix ys xs" then have "prefixeq ys (xs @ [x])" by (simp add: prefix_def) with snoc have False by blast then show ?thesis .. next @@ -325,14 +320,14 @@ by (induct zs) (auto intro!: suffixeq_appendI suffixeq_ConsI) qed -lemma suffixeq_to_prefixeq [code]: "suffixeq xs ys \ rev xs \ rev ys" +lemma suffixeq_to_prefixeq [code]: "suffixeq xs ys \ prefixeq (rev xs) (rev ys)" proof assume "suffixeq xs ys" then obtain zs where "ys = zs @ xs" .. then have "rev ys = rev xs @ rev zs" by simp - then show "rev xs <= rev ys" .. + then show "prefixeq (rev xs) (rev ys)" .. next - assume "rev xs <= rev ys" + assume "prefixeq (rev xs) (rev ys)" then obtain zs where "rev ys = rev xs @ zs" .. then have "rev (rev ys) = rev zs @ rev (rev xs)" by simp then have "ys = rev zs @ xs" by simp @@ -375,10 +370,10 @@ qed qed -lemma parallelD1: "x \ y \ \ x \ y" +lemma parallelD1: "x \ y \ \ prefixeq x y" by blast -lemma parallelD2: "x \ y \ \ y \ x" +lemma parallelD2: "x \ y \ \ prefixeq y x" by blast lemma parallel_Nil1 [simp]: "\ x \ []" @@ -481,4 +476,7 @@ shows "emb P xs zs" using assms and emb_suffix unfolding suffixeq_suffix_reflclp_conv by auto +lemma emb_length: "emb P xs ys \ length xs \ length ys" + by (induct rule: emb.induct) auto + end