X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=matita%2Fmatita%2Flib%2Fbasics%2Flists%2Flist.ma;h=a330f6224ef1fdb6c94e356b71955f9bad0129e5;hb=85a42e4a2a4c62818b6a98eff545e58ceb8770a4;hp=edc049738b5c5a5f01b98698dc6ac1fadec15d87;hpb=ae14e3f084ff70d37842603fa41800641e08b51a;p=helm.git diff --git a/matita/matita/lib/basics/lists/list.ma b/matita/matita/lib/basics/lists/list.ma index edc049738..a330f6224 100644 --- a/matita/matita/lib/basics/lists/list.ma +++ b/matita/matita/lib/basics/lists/list.ma @@ -84,6 +84,14 @@ theorem nil_to_nil: ∀A.∀l1,l2:list A. #A #l1 #l2 #isnil @(nil_append_elim A l1 l2) /2/ qed. +lemma cons_injective_l : ∀A.∀a1,a2:A.∀l1,l2.a1::l1 = a2::l2 → a1 = a2. +#A #a1 #a2 #l1 #l2 #Heq destruct // +qed. + +lemma cons_injective_r : ∀A.∀a1,a2:A.∀l1,l2.a1::l1 = a2::l2 → l1 = l2. +#A #a1 #a2 #l1 #l2 #Heq destruct // +qed. + (**************************** iterators ******************************) let rec map (A,B:Type[0]) (f: A → B) (l:list A) on l: list B ≝ @@ -183,16 +191,78 @@ lemma length_map: ∀A,B,l.∀f:A→B. length ? (map ?? f l) = length ? l. #A #B #l #f elim l // #a #tl #Hind normalize // qed. +lemma length_reverse: ∀A.∀l:list A. + |reverse A l| = |l|. +#A #l elim l // #a #l0 #IH >reverse_cons >length_append normalize // +qed. + +lemma lenght_to_nil: ∀A.∀l:list A. + |l| = 0 → l = [ ]. +#A * // #a #tl normalize #H destruct +qed. + +(****************** traversing two lists in parallel *****************) +lemma list_ind2 : + ∀T1,T2:Type[0].∀l1:list T1.∀l2:list T2.∀P:list T1 → list T2 → Prop. + length ? l1 = length ? l2 → + (P [] []) → + (∀tl1,tl2,hd1,hd2. P tl1 tl2 → P (hd1::tl1) (hd2::tl2)) → + P l1 l2. +#T1 #T2 #l1 #l2 #P #Hl #Pnil #Pcons +generalize in match Hl; generalize in match l2; +elim l1 +[#l2 cases l2 // normalize #t2 #tl2 #H destruct +|#t1 #tl1 #IH #l2 cases l2 + [normalize #H destruct + |#t2 #tl2 #H @Pcons @IH normalize in H; destruct // ] +] +qed. + +lemma list_cases2 : + ∀T1,T2:Type[0].∀l1:list T1.∀l2:list T2.∀P:Prop. + length ? l1 = length ? l2 → + (l1 = [] → l2 = [] → P) → + (∀hd1,hd2,tl1,tl2.l1 = hd1::tl1 → l2 = hd2::tl2 → P) → P. +#T1 #T2 #l1 #l2 #P #Hl @(list_ind2 … Hl) +[ #Pnil #Pcons @Pnil // +| #tl1 #tl2 #hd1 #hd2 #IH1 #IH2 #Hp @Hp // ] +qed. + +(*********************** properties of append ***********************) +lemma append_l1_injective : + ∀A.∀l1,l2,l3,l4:list A. |l1| = |l2| → l1@l3 = l2@l4 → l1 = l2. +#a #l1 #l2 #l3 #l4 #Hlen @(list_ind2 … Hlen) // +#tl1 #tl2 #hd1 #hd2 #IH normalize #Heq destruct @eq_f /2/ +qed. + +lemma append_l2_injective : + ∀A.∀l1,l2,l3,l4:list A. |l1| = |l2| → l1@l3 = l2@l4 → l3 = l4. +#a #l1 #l2 #l3 #l4 #Hlen @(list_ind2 … Hlen) normalize // +#tl1 #tl2 #hd1 #hd2 #IH normalize #Heq destruct /2/ +qed. + +lemma append_l1_injective_r : + ∀A.∀l1,l2,l3,l4:list A. |l3| = |l4| → l1@l3 = l2@l4 → l1 = l2. +#a #l1 #l2 #l3 #l4 #Hlen #Heq lapply (eq_f … (reverse ?) … Heq) +>reverse_append >reverse_append #Heq1 +lapply (append_l2_injective … Heq1) [ // ] #Heq2 +lapply (eq_f … (reverse ?) … Heq2) // +qed. + +lemma append_l2_injective_r : + ∀A.∀l1,l2,l3,l4:list A. |l3| = |l4| → l1@l3 = l2@l4 → l3 = l4. +#a #l1 #l2 #l3 #l4 #Hlen #Heq lapply (eq_f … (reverse ?) … Heq) +>reverse_append >reverse_append #Heq1 +lapply (append_l1_injective … Heq1) [ // ] #Heq2 +lapply (eq_f … (reverse ?) … Heq2) // +qed. + lemma length_rev_append: ∀A.∀l,acc:list A. |rev_append ? l acc| = |l|+|acc|. #A #l elim l // #a #tl #Hind normalize #acc >Hind normalize // qed. -lemma length_reverse: ∀A.∀l:list A. - |reverse A l| = |l|. -// qed. - (****************************** mem ********************************) let rec mem A (a:A) (l:list A) on l ≝ match l with @@ -200,6 +270,27 @@ let rec mem A (a:A) (l:list A) on l ≝ | cons hd tl ⇒ a=hd ∨ mem A a tl ]. +lemma mem_map: ∀A,B.∀f:A→B.∀l,b. + mem ? b (map … f l) → ∃a. mem ? a l ∧ f a = b. +#A #B #f #l elim l + [#b normalize @False_ind + |#a #tl #Hind #b normalize * + [#eqb @(ex_intro … a) /3/ + |#memb cases (Hind … memb) #a * #mema #eqb + @(ex_intro … a) /3/ + ] + ] +qed. + +lemma mem_map_forward: ∀A,B.∀f:A→B.∀a,l. + mem A a l → mem B (f a) (map ?? f l). + #A #B #f #a #l elim l + [normalize @False_ind + |#b #tl #Hind * + [#eqab Hnil >length_append >length_append //] /2/ + |#hd #tl #Hind #l1 #l2 #a #posn #Hlen #Ha + whd in match (flatten ??); #Hflat * #q cases q + [(lenght_to_nil… Hl1) in Hflat; + whd in ⊢ ((???%)→?); #Hflat @sym_eq @(append_l1_injective … Hflat) + >Ha >Hlen // %1 // + ] /2/ + |#q1 #Hl1 lapply (split_exists … n l1 ?) // + * #l11 * #l12 * #Heql1 #Hlenl11 %2 + @(Hind l12 l2 … posn ? Ha) + [#x #memx @Hlen %2 // + |@(append_l2_injective ? hd l11) + [>Hlenl11 @Hlen %1 % + |>Hflat >Heql1 >associative_append % + ] + |@(ex_intro …q1) @(injective_plus_r n) + Hl1 // + ] + ] + ] +qed. + (****************************** nth ********************************) let rec nth n (A:Type[0]) (l:list A) (d:A) ≝ match n with