[3554] | 1 | (**************************************************************************) |
---|
| 2 | (* ___ *) |
---|
| 3 | (* ||M|| *) |
---|
| 4 | (* ||A|| A project by Andrea Asperti *) |
---|
| 5 | (* ||T|| *) |
---|
| 6 | (* ||I|| Developers: *) |
---|
| 7 | (* ||T|| The HELM team. *) |
---|
| 8 | (* ||A|| http://helm.cs.unibo.it *) |
---|
| 9 | (* \ / *) |
---|
| 10 | (* \ / This file is distributed under the terms of the *) |
---|
| 11 | (* v GNU General Public License Version 2 *) |
---|
| 12 | (* *) |
---|
| 13 | (**************************************************************************) |
---|
| 14 | |
---|
| 15 | include "basics/lists/listb.ma". |
---|
| 16 | include "../src/utilities/hide.ma". |
---|
| 17 | include "../src/ASM/Util.ma". |
---|
| 18 | include "../src/utilities/option.ma". |
---|
| 19 | |
---|
[3574] | 20 | definition update_fun : ∀A : DeqSet.∀B : Type[0].(A → B) → A → B → A → B ≝ |
---|
| 21 | λA,B,f,a,b,x.if x == a then b else f x. |
---|
| 22 | |
---|
[3563] | 23 | lemma bind_inversion : ∀A,B : Type[0].∀m : option A. |
---|
| 24 | ∀f : A → option B.∀y : B. |
---|
| 25 | ! x ← m; f x = return y → |
---|
| 26 | ∃ x.(m = return x) ∧ (f x = return y). |
---|
| 27 | #A #B * [| #a] #f #y normalize #EQ [destruct] |
---|
| 28 | %{a} %{(refl …)} // |
---|
| 29 | qed. |
---|
| 30 | |
---|
[3554] | 31 | (*NO DUPLICATES in lists*) |
---|
| 32 | |
---|
| 33 | let rec no_duplicates (A : DeqSet) (l : list A) on l : Prop ≝ |
---|
| 34 | match l with |
---|
| 35 | [ nil ⇒ True |
---|
| 36 | | cons x xs ⇒ ¬ (bool_to_Prop (x ∈ xs)) ∧ no_duplicates … xs |
---|
| 37 | ]. |
---|
| 38 | |
---|
| 39 | lemma no_duplicates_append_r : ∀A : DeqSet.∀l1,l2 : list A.no_duplicates … (l1 @ l2) → |
---|
| 40 | no_duplicates … l2. |
---|
| 41 | #A #l1 elim l1 // #x #xs normalize #IH #l2 * /2/ |
---|
| 42 | qed. |
---|
| 43 | |
---|
| 44 | lemma no_duplicates_append_l : ∀A : DeqSet.∀l1,l2 : list A.no_duplicates … (l1 @ l2) → |
---|
| 45 | no_duplicates … l1. |
---|
| 46 | #A #l1 elim l1 // #x #xs normalize #IH #l2 * #H1 #H2 % [2: /2/ ] |
---|
| 47 | inversion(x ∈ xs @l2) in H1; normalize [ #_ * #H @⊥ @H %] #H1 #_ |
---|
| 48 | % inversion(x ∈ xs) normalize [2: //] #H3 #_ >(memb_append_l1 … H3) in H1; |
---|
| 49 | #EQ destruct(EQ) |
---|
| 50 | qed. |
---|
| 51 | |
---|
| 52 | lemma no_duplicates_append_commute : ∀ A : DeqSet.∀l1,l2 : list A. |
---|
| 53 | no_duplicates … (l1 @ l2) → |
---|
| 54 | no_duplicates … (l2 @ l1). |
---|
| 55 | #A #l1 elim l1 |
---|
| 56 | [ #l2 >append_nil //] |
---|
| 57 | #x #xs #IH #l2 * #H1 #H2 lapply(IH … H2) lapply H1 -H1 -IH -H2 |
---|
| 58 | elim l2 -l1 |
---|
| 59 | [ >append_nil #H1 #H2 % // ] |
---|
| 60 | #y #ys #IH * #H1 * #H2 #H3 % |
---|
| 61 | [2: @IH |
---|
| 62 | [ % #H4 @H1 cases(memb_append … H4) |
---|
| 63 | [ #H5 >memb_append_l1 // |
---|
| 64 | | #H5 >memb_append_l2 // @orb_Prop_r >H5 // |
---|
| 65 | ] |
---|
| 66 | | // |
---|
| 67 | ] |
---|
| 68 | | % #H4 cases(memb_append … H4) |
---|
| 69 | [ #H5 @(absurd ?? H2) >memb_append_l1 // |
---|
| 70 | | whd in match (memb ???); inversion(y==x) |
---|
| 71 | [ #H5 #_ <(\P H5) in H1; #H1 @H1 >memb_append_l2 // |
---|
| 72 | | #_ normalize nodelta #H5 @(absurd ?? H2) >memb_append_l2 // |
---|
| 73 | ] |
---|
| 74 | ] |
---|
| 75 | ] |
---|
| 76 | qed. |
---|
| 77 | |
---|
| 78 | lemma memb_not_append : ∀D : DeqSet.∀l1,l2 : list D.∀x : D. |
---|
| 79 | x ∈ l1 = false → x ∈ l2 = false → x ∈ (l1 @ l2) = false. |
---|
| 80 | #D #l1 elim l1 |
---|
| 81 | [ #l2 #x #_ #H @H ] |
---|
| 82 | #x #xs #IH #l2 #x1 whd in match (memb ???); inversion (x1 == x) normalize nodelta |
---|
| 83 | [ #_ #EQ destruct] #EQx1 #EQxs #EQl2 whd in match (memb ???); >EQx1 |
---|
| 84 | normalize nodelta @IH // |
---|
| 85 | qed. |
---|
| 86 | |
---|
| 87 | lemma memb_no_duplicates_append : ∀A : DeqSet.∀x.∀l1,l2 : list A . |
---|
| 88 | no_duplicates … (l1 @ l2) → x ∈ l1 → x ∈ l2 → False. |
---|
| 89 | #A #x #l1 elim l1 // #x1 #xs #IH #l2 * #H1 #H2 whd in match (memb ???); |
---|
| 90 | inversion (x == x1) normalize nodelta |
---|
| 91 | [ #H3 #_ #H4 >memb_append_l2 in H1; [2: <(\P H3) @H4 ] * #H @H % |
---|
| 92 | | #_ @IH // |
---|
| 93 | ] |
---|
| 94 | qed. |
---|
| 95 | |
---|
| 96 | (* subset *) |
---|
| 97 | |
---|
| 98 | let rec subset (A : Type[0]) (l1,l2 : list A) on l1 : Prop ≝ |
---|
| 99 | match l1 with |
---|
| 100 | [ nil ⇒ True |
---|
| 101 | | cons x xs ⇒ mem … x l2 ∧ subset … xs l2 |
---|
| 102 | ]. |
---|
| 103 | |
---|
| 104 | interpretation "subset" 'subseteq a b = (subset ? a b). |
---|
| 105 | |
---|
| 106 | lemma subset_append_l2 : ∀A,l2,l1.subset A l2 (l1 @ l2). |
---|
| 107 | #A #l2 elim l2 // normalize #x #xs #IH #l1 % // @mem_append_l2 whd /2/ |
---|
| 108 | qed. |
---|
| 109 | |
---|
| 110 | lemma refl_subset : ∀A.reflexive … (subset A). |
---|
| 111 | #A #l1 elim l1 // #x #xs #IH normalize % /2/ change with ([?]@xs) in match (x :: xs); |
---|
| 112 | @subset_append_l2 |
---|
| 113 | qed. |
---|
| 114 | |
---|
| 115 | lemma subset_def : ∀A : DeqSet.∀l1,l2 : list A.(∀x.x ∈l1 → x ∈ l2) → l1 ⊆ l2. |
---|
| 116 | #A #l1 elim l1 // #x #xs #IH #l2 #H % |
---|
| 117 | [ @memb_to_mem >H // >memb_hd // |
---|
| 118 | | @IH #y #H1 @H >memb_cons // >H1 // |
---|
| 119 | ] |
---|
| 120 | qed. |
---|
| 121 | |
---|
| 122 | lemma subset_append : ∀A.∀l1,l2,l3 : list A.l1 ⊆ l3 → l2 ⊆ l3 → (l1 @ l2) ⊆ l3. |
---|
| 123 | #A #l1 elim l1 // #x #xs #IH #l2 #l3 * #H1 #H2 #H3 % /2/ |
---|
| 124 | qed. |
---|
| 125 | |
---|
| 126 | lemma subset_def_inv : ∀A.∀l1,l2 : list A. l1 ⊆ l2 → ∀x.mem … x l1 → mem … x l2. |
---|
| 127 | #A #l1 elim l1 [ #l2 * #x * ] #x #xs #IH #l2 * #H1 #H2 #y * |
---|
| 128 | [ #EQ destruct // | #H3 @IH // ] |
---|
| 129 | qed. |
---|
| 130 | |
---|
| 131 | lemma transitive_subset : ∀A.transitive … (subset A). |
---|
| 132 | #A #l1 elim l1 // #x #xs #IH #l2 #l3 * #H1 #H2 #H3 % |
---|
| 133 | [ @(subset_def_inv … H3) // | @IH // ] |
---|
| 134 | qed. |
---|
| 135 | |
---|
| 136 | lemma subset_append_h1 : ∀A.∀l1,l2,l3 : list A.l1 ⊆ l3 → l1 ⊆ (l3 @ l2). |
---|
| 137 | #A #l1 elim l1 // #x #x2 #IH #l2 #l3 * #H1 #H2 % [ @mem_append_l1 // | @IH // ] |
---|
| 138 | qed. |
---|
| 139 | |
---|
| 140 | lemma subset_append_h2 : ∀A.∀l1,l2,l3 : list A.l2 ⊆ l3 → l2 ⊆ (l1 @ l3). |
---|
| 141 | #A #l1 elim l1 // #x #xs #IH #l2 elim l2 // #y #ys #IH #l3 * #H1 #H2 % |
---|
| 142 | [ @mem_append_l2 // | @IH // ] |
---|
| 143 | qed. |
---|
| 144 | |
---|
[3575] | 145 | (* some useful deqsets *) |
---|
| 146 | |
---|
| 147 | definition DeqUnit ≝ mk_DeqSet unit (λ_.λ_.true) ?. |
---|
| 148 | @hide_prf ** % // qed. |
---|
| 149 | |
---|
| 150 | definition DeqFalse ≝ mk_DeqSet False (λ_.λ_.true) ?. |
---|
| 151 | @hide_prf * qed. |
---|
| 152 | |
---|
[3554] | 153 | (* list of elements with decidable equality *) |
---|
| 154 | |
---|
| 155 | let rec eqb_list (D : DeqSet) (l1 : list D) on l1 : list D → bool ≝ |
---|
| 156 | match l1 with |
---|
| 157 | [ nil ⇒ λl2.match l2 with [nil ⇒ true | _ ⇒ false ] |
---|
| 158 | | cons x xs ⇒ λl2.match l2 with [ cons y ys ⇒ x == y ∧ eqb_list … xs ys | _ ⇒ false ] |
---|
| 159 | ]. |
---|
| 160 | |
---|
| 161 | definition DeqSet_List : DeqSet → DeqSet ≝ |
---|
| 162 | λX.mk_DeqSet (list X) (eqb_list …) ?. |
---|
| 163 | #x elim x [ * /2 by refl, conj/ #y #ys normalize % #EQ destruct] -x |
---|
| 164 | #x #xs #IH * [ normalize % #EQ destruct] #y #ys normalize % inversion(x == y) |
---|
| 165 | #EQ normalize nodelta |
---|
| 166 | [ #H >(proj1 … (IH ys) H) @eq_f2 [2: %] @(proj1 … (eqb_true …)) assumption |
---|
| 167 | | #EQ destruct |
---|
| 168 | | #EQ1 destruct @(proj2 … (IH …)) % |
---|
| 169 | | #EQ1 destruct <EQ @(proj2 … (eqb_true …)) % |
---|
| 170 | ] |
---|
| 171 | qed. |
---|
| 172 | |
---|
| 173 | unification hint 0 ≔ C; |
---|
| 174 | X ≟ DeqSet_List C |
---|
| 175 | (* ---------------------------------------- *) ⊢ |
---|
| 176 | list C ≡ carr X. |
---|
| 177 | |
---|
| 178 | |
---|
| 179 | unification hint 0 ≔ D,p1,p2; |
---|
| 180 | X ≟ DeqSet_List D |
---|
| 181 | (* ---------------------------------------- *) ⊢ |
---|
| 182 | eqb_list D p1 p2 ≡ eqb X p1 p2. |
---|
| 183 | |
---|
| 184 | lemma mem_list : ∀A : Type[0]. |
---|
| 185 | ∀l : list A.∀x : A.mem … x l → |
---|
| 186 | ∃l1,l2.l=l1 @ [x] @ l2. |
---|
| 187 | #A #l elim l |
---|
| 188 | [ #x *] |
---|
| 189 | #x #xs #IH #y * |
---|
| 190 | [ #EQ destruct %{[]} %{xs} % |
---|
| 191 | | #H cases(IH … H) #l1 * #l2 #EQ destruct |
---|
| 192 | %{(x :: l1)} %{l2} % |
---|
| 193 | ] |
---|
| 194 | qed. |
---|
| 195 | |
---|
| 196 | (* associative list *) |
---|
| 197 | |
---|
| 198 | definition associative_list : DeqSet → Type[0] → Type[0] ≝ |
---|
| 199 | λA,B.list (A × (list B)). |
---|
| 200 | |
---|
| 201 | let rec update_list (A : DeqSet) (B : Type[0]) (l : associative_list A B) |
---|
| 202 | on l : A → list B → associative_list A B ≝ |
---|
| 203 | λa,b.match l with |
---|
| 204 | [ nil ⇒ [〈a,b〉] |
---|
| 205 | | cons x xs ⇒ if (a == (\fst x)) then 〈a,b〉 :: xs |
---|
| 206 | else x :: (update_list … xs a b) |
---|
| 207 | ]. |
---|
| 208 | |
---|
| 209 | let rec get_element (A :DeqSet) (B : Type[0]) (l: associative_list A B) on l : A → list B ≝ |
---|
| 210 | λa.match l with [ nil ⇒ nil ? |
---|
| 211 | | cons x xs ⇒ if (a == \fst x) then \snd x else get_element … xs a |
---|
| 212 | ]. |
---|
| 213 | |
---|
| 214 | let rec domain_of_associative_list (A :DeqSet) (B : Type[0]) (l: associative_list A B) on l : list A ≝ |
---|
| 215 | match l with |
---|
| 216 | [ nil ⇒ [] |
---|
| 217 | | cons x xs ⇒ \fst x :: domain_of_associative_list … xs |
---|
| 218 | ]. |
---|
| 219 | |
---|
| 220 | lemma get_element_append_l: |
---|
| 221 | ∀A,B. ∀l1,l2: associative_list A B. ∀x. |
---|
| 222 | x ∈ domain_of_associative_list … l1 → |
---|
| 223 | get_element … (l1@l2) x = get_element … l1 x. |
---|
| 224 | #A #B #l1 elim l1 normalize [ #l2 #x * ] #hd #tl #IH #l2 #x cases (dec_eq … x (\fst hd)) |
---|
| 225 | #H [ >(\b H) | >(\bf H) ] normalize /2/ |
---|
| 226 | qed. |
---|
| 227 | |
---|
| 228 | lemma get_element_append_r: |
---|
| 229 | ∀A,B. ∀l1,l2: associative_list A B. ∀x. |
---|
| 230 | ¬ (bool_to_Prop (x ∈ domain_of_associative_list … l1)) → |
---|
| 231 | get_element ?? (l1@l2) x = get_element … l2 x. |
---|
| 232 | #A #B #l1 elim l1 normalize [ #l2 #x // ] #hd #tl #IH #l2 #x cases (dec_eq … x (\fst hd)) |
---|
| 233 | #H [ >(\b H) | >(\bf H) ] normalize /2 by/ * #K cases (K I) |
---|
| 234 | qed. |
---|
| 235 | |
---|
| 236 | lemma get_element_append_l1 : |
---|
| 237 | ∀A,B. ∀l1,l2: associative_list A B. ∀x. |
---|
| 238 | ¬ (bool_to_Prop (x ∈ domain_of_associative_list … l2)) → |
---|
| 239 | get_element ?? (l1@l2) x = get_element … l1 x. |
---|
| 240 | #A #B #l1 elim l1 normalize [2: #x #xs #IH #l2 #a #H >IH // ] |
---|
| 241 | #l2 elim l2 // #y #ys #IH #a normalize cases(a == \fst y) normalize |
---|
| 242 | [ * #H @⊥ @H % ] #H @IH assumption |
---|
| 243 | qed. |
---|
| 244 | |
---|
| 245 | lemma get_element_append_r1 : |
---|
| 246 | ∀A,B. ∀l1,l2: associative_list A B. ∀x. |
---|
| 247 | ¬ (bool_to_Prop (x ∈ domain_of_associative_list … l1)) → |
---|
| 248 | get_element ?? (l1@l2) x = get_element … l2 x. |
---|
| 249 | #A #B #l1 elim l1 normalize // #x #xs #IH #l2 #a cases (?==?) |
---|
| 250 | normalize [* #H cases H //] #H >IH normalize // |
---|
| 251 | qed. |
---|
| 252 | |
---|
| 253 | lemma memb_append_l22 : ∀A : DeqSet.∀x : A.∀l1,l2 : list A. |
---|
| 254 | ¬ (x ∈ l1) → x∈ l1 @ l2 = (x ∈ l2). |
---|
| 255 | #A #x #l1 elim l1 normalize // #y #ys #IH #l2 cases(x==y) |
---|
| 256 | normalize [*] @IH |
---|
| 257 | qed. |
---|
| 258 | |
---|
| 259 | lemma memb_append_l12 : ∀A : DeqSet.∀x : A.∀l1,l2 : list A. |
---|
| 260 | ¬ (x ∈ l2) → x∈ l1 @ l2 = (x ∈ l1). |
---|
| 261 | #A #x #l1 elim l1 |
---|
| 262 | [ #l2 #H whd in match (append ???); @not_b_to_eq_false @Prop_notb >H % ] |
---|
| 263 | #y #ys #IH #l2 #H1 whd in match (memb ???); >IH // |
---|
| 264 | qed. |
---|
| 265 | |
---|
| 266 | lemma foldr_map_append : |
---|
| 267 | ∀A,B:Type[0]. ∀l1, l2 : list A. |
---|
| 268 | ∀f:A → list B. ∀seed. |
---|
| 269 | foldr ?? (λx,acc. (f x) @ acc) seed (l1 @ l2) = |
---|
| 270 | append ? (foldr ?? (λx,acc. (f x) @ acc) (nil ?) l1) |
---|
| 271 | (foldr ?? (λx,acc. (f x) @ acc) seed l2). |
---|
| 272 | #A #B #l1 elim l1 normalize // /3 by eq_f, trans_eq/ |
---|
| 273 | qed. |
---|
| 274 | |
---|
| 275 | lemma cons_append : ∀A.∀x : A.∀l.x::l = ([x]@l). |
---|
| 276 | // |
---|
| 277 | qed. |
---|
| 278 | |
---|
| 279 | lemma domain_of_associative_list_append : ∀A,B.∀l1,l2 : associative_list A B. |
---|
| 280 | domain_of_associative_list ?? (l1 @ l2) = |
---|
| 281 | (domain_of_associative_list ?? l1) @ (domain_of_associative_list ?? l2). |
---|
| 282 | #A #B #l1 elim l1 // #x #xs #IH #l2 normalize // |
---|
| 283 | qed. |
---|
| 284 | |
---|
| 285 | (*monoids*) |
---|
| 286 | |
---|
| 287 | record monoid: Type[1] ≝ |
---|
| 288 | { carrier :> DeqSet |
---|
| 289 | ; op: carrier → carrier → carrier |
---|
| 290 | ; e: carrier |
---|
| 291 | ; neutral_r : ∀x. op … x e = x |
---|
| 292 | ; neutral_l : ∀x. op … e x = x |
---|
| 293 | ; is_associative: ∀x,y,z. op … (op … x y) z = op … x (op … y z) |
---|
| 294 | }. |
---|
| 295 | |
---|
| 296 | definition is_abelian ≝ λM : monoid. |
---|
| 297 | ∀x,y : M.op … M x y = op … M y x. |
---|
| 298 | |
---|
| 299 | record monoid_action (I : monoid) (M : Type[0]) : Type[0] ≝ |
---|
| 300 | { act :2> I → M → M |
---|
| 301 | ; act_neutral : ∀x.act (e …) x = x |
---|
| 302 | ; act_op : ∀i,j,x.act (op … i j) x = act j (act i x) |
---|
| 303 | }. |
---|
| 304 | |
---|
| 305 | (* partial order *) |
---|
| 306 | |
---|
| 307 | record partial_order (A : Type[0]) : Type[0] ≝ |
---|
| 308 | { po_rel :2> A → A → Prop |
---|
| 309 | ; refl_po_rel : reflexive … po_rel |
---|
| 310 | ; antisym_po_rel : ∀x,y : A.po_rel … x y → po_rel … y x → x = y |
---|
| 311 | ; trans_po_rel : transitive … po_rel |
---|
| 312 | }. |
---|
| 313 | |
---|
| 314 | (* fold2 *) |
---|
| 315 | |
---|
| 316 | let rec foldr2 (A : Type[0]) (B : Type[0]) (C : Type[0]) (a : A) (l1 : list B) |
---|
| 317 | (l2 : list C) (f : A → B → C → A) on l1 : option A≝ |
---|
| 318 | match l1 with |
---|
| 319 | [ nil ⇒ match l2 with [ nil ⇒ return a | cons y ys ⇒ None ? ] |
---|
| 320 | | cons x xs ⇒ |
---|
| 321 | match l2 with |
---|
| 322 | [ nil ⇒ None ? |
---|
| 323 | | cons y ys ⇒ ! ih ← (foldr2 … a xs ys f); |
---|
| 324 | return f ih x y |
---|
| 325 | ] |
---|
| 326 | ]. |
---|
| 327 | |
---|
| 328 | (* dependent map*) |
---|
| 329 | |
---|
| 330 | let rec dependent_map (A,B : Type[0]) (l : list A) (f : ∀a : A.mem … a l → B) on l : list B ≝ |
---|
| 331 | (match l return λx.l=x → ? with |
---|
| 332 | [ nil ⇒ λ_.nil ? |
---|
| 333 | | cons x xs ⇒ λprf.(f x ?) :: dependent_map A B xs (λx,prf1.f x ?) |
---|
| 334 | ])(refl …). |
---|
| 335 | [ >prf %% | >prf %2 assumption] |
---|
| 336 | qed. |
---|
| 337 | |
---|
| 338 | lemma dependent_map_append : ∀A,B,l1,l2,f. |
---|
| 339 | dependent_map A B (l1 @ l2) (λa,prf.f a prf) = |
---|
| 340 | (dependent_map A B l1 (λa,prf.f a ?)) @ (dependent_map A B l2 (λa,prf.f a ?)). |
---|
| 341 | [2: @hide_prf /2/ | 3: @hide_prf /2/] |
---|
| 342 | #A #B #l1 elim l1 normalize /2/ |
---|
| 343 | qed. |
---|
| 344 | |
---|
| 345 | lemma rewrite_in_dependent_map : ∀A,B,l1,l2,f. |
---|
| 346 | ∀EQ:l1 = l2. |
---|
| 347 | dependent_map A B l1 (λa,prf.f a prf) = |
---|
| 348 | dependent_map A B l2 (λa,prf.f a ?). |
---|
| 349 | [2: >EQ // | #A #B #l1 #l2 #f #EQ >EQ in f; #f % ] |
---|
| 350 | qed. |
---|
| 351 | |
---|
| 352 | definition applica : ∀A,B : Type[0].∀ l : list A.(∀a : A.mem … a l → B) → ∀a : A.mem … a l → B ≝ |
---|
| 353 | λA,B,l,f,x,prf.f x prf. |
---|
| 354 | |
---|
| 355 | lemma proof_irrelevance_temp : ∀A,B : Type[0].∀l : list A. |
---|
| 356 | ∀f : (∀a : A.mem … a l → B).∀x.∀prf1,prf2. |
---|
| 357 | applica … f x prf1 = applica … f x prf2. |
---|
| 358 | // |
---|
| 359 | qed. |
---|
| 360 | |
---|
| 361 | lemma proof_irrelevance_all : ∀A,B : Type[0].∀l : list A. |
---|
| 362 | ∀f : (∀a : A.mem … a l → B).∀x.∀prf1,prf2. |
---|
| 363 | f x prf1 = f x prf2. |
---|
| 364 | #A #B #l #f #x #prf1 #prf2 @proof_irrelevance_temp |
---|
| 365 | qed. |
---|
| 366 | |
---|
| 367 | lemma dependent_map_extensional : ∀A,B : Type[0].∀l : list A. |
---|
| 368 | ∀f,g : (∀a.mem … a l → B).(∀a,prf1,prf2.f a prf1 = g a prf2) → |
---|
| 369 | dependent_map … l f = dependent_map … l g. |
---|
| 370 | #A #B #l elim l // #x #xs #IH #f #g #H whd in ⊢ (??%%); |
---|
| 371 | @eq_f2 // @IH // |
---|
[3563] | 372 | qed. |
---|
[3574] | 373 | |
---|
| 374 | (* nth_opt*) |
---|
| 375 | |
---|
| 376 | lemma nth_first : ∀A.∀l1,l2 : list A.∀n : ℕ.|l1| > n → nth_opt … n (l1 @ l2) = nth_opt … n l1. |
---|
| 377 | #A #l1 elim l1 [ #l2 #n normalize #H @⊥ /2/] #x #xs #IH #l2 * // #n #H @IH normalize in H; /2/ |
---|
| 378 | qed. |
---|
| 379 | |
---|
| 380 | lemma nth_second : ∀A.∀l1,l2 : list A.∀n : ℕ.|l1| ≤ n → nth_opt … n (l1 @ l2) = nth_opt … (n - |l1|) l2. |
---|
| 381 | #A #l1 elim l1 [normalize //] #x #xs #IH #l2 * [ normalize #H @⊥ /2/] #n #H normalize @IH /2/ |
---|
| 382 | qed. |
---|