source: src/ASM/Util.ma

Last change on this file was 3466, checked in by asperti, 5 years ago

Removed function that is only in the standard library.
Maaaany more to be removed.

File size: 41.4 KB
Line 
1include "basics/lists/list.ma".
2include "basics/types.ma".
3include "arithmetics/nat.ma".
4include "basics/russell.ma".
5
6(* let's implement a daemon not used by automation *)
7inductive DAEMONXXX: Type[0] ≝ K1DAEMONXXX: DAEMONXXX | K2DAEMONXXX: DAEMONXXX.
8axiom IMPOSSIBLE: K1DAEMONXXX = K2DAEMONXXX.
9example daemon: False. generalize in match IMPOSSIBLE; #IMPOSSIBLE destruct(IMPOSSIBLE) qed.
10example not_implemented: False. cases daemon qed.
11
12notation "⊥" with precedence 90
13  for @{ match ? in False with [ ] }.
14notation "Ⓧ" with precedence 90
15  for @{ λabs.match abs in False with [ ] }.
16
17
18definition ltb ≝
19  λm, n: nat.
20    leb (S m) n.
21   
22definition geb ≝
23  λm, n: nat.
24    leb n m.
25
26definition gtb ≝
27  λm, n: nat.
28    ltb n m.
29
30(* dpm: unless I'm being stupid, this isn't defined in the stdlib? *)
31let rec eq_nat (n: nat) (m: nat) on n: bool ≝
32  match n with
33  [ O ⇒ match m with [ O ⇒ true | _ ⇒ false ]
34  | S n' ⇒ match m with [ S m' ⇒ eq_nat n' m' | _ ⇒ false ]
35  ].
36
37let rec forall
38  (A: Type[0]) (f: A → bool) (l: list A)
39    on l ≝
40  match l with
41  [ nil        ⇒ true
42  | cons hd tl ⇒ f hd ∧ forall A f tl
43  ].
44
45let rec prefix
46  (A: Type[0]) (k: nat) (l: list A)
47    on l ≝
48  match l with
49  [ nil ⇒ [ ]
50  | cons hd tl ⇒
51    match k with
52    [ O ⇒ [ ]
53    | S k' ⇒ hd :: prefix A k' tl
54    ]
55  ].
56 
57let rec fold_left2
58  (A: Type[0]) (B: Type[0]) (C: Type[0]) (f: A → B → C → A) (accu: A)
59  (left: list B) (right: list C) (proof: |left| = |right|)
60    on left: A ≝
61  match left return λx. |x| = |right| → A with
62  [ nil ⇒ λnil_prf.
63    match right return λx. |[ ]| = |x| → A with
64    [ nil ⇒ λnil_nil_prf. accu
65    | cons hd tl ⇒ λcons_nil_absrd. ?
66    ] nil_prf
67  | cons hd tl ⇒ λcons_prf.
68    match right return λx. |hd::tl| = |x| → A with
69    [ nil ⇒ λcons_nil_absrd. ?
70    | cons hd' tl' ⇒ λcons_cons_prf.
71        fold_left2 …  f (f accu hd hd') tl tl' ?
72    ] cons_prf
73  ] proof.
74  [ 1: normalize in cons_nil_absrd;
75       destruct(cons_nil_absrd)
76  | 2: normalize in cons_nil_absrd;
77       destruct(cons_nil_absrd)
78  | 3: normalize in cons_cons_prf;
79       @injective_S
80       assumption
81  ]
82qed.
83
84let rec remove_n_first_internal
85  (i: nat) (A: Type[0]) (l: list A) (n: nat)
86    on l ≝
87  match l with
88  [ nil ⇒ [ ]
89  | cons hd tl ⇒
90    match eq_nat i n with
91    [ true ⇒ l
92    | _ ⇒ remove_n_first_internal (S i) A tl n
93    ]
94  ].
95
96definition remove_n_first ≝
97  λA: Type[0].
98  λn: nat.
99  λl: list A.
100    remove_n_first_internal 0 A l n.
101   
102let rec foldi_from_until_internal
103  (A: Type[0]) (i: nat) (res: ?) (rem: list A) (m: nat) (f: nat → list A → A → list A)
104    on rem ≝
105  match rem with
106  [ nil ⇒ res
107  | cons e tl ⇒
108    match geb i m with
109    [ true ⇒ res
110    | _ ⇒ foldi_from_until_internal A (S i) (f i res e) tl m f
111    ]
112  ].
113
114definition foldi_from_until ≝
115  λA: Type[0].
116  λn: nat.
117  λm: nat.
118  λf: ?.
119  λa: ?.
120  λl: ?.
121    foldi_from_until_internal A 0 a (remove_n_first A n l) m f.
122
123definition foldi_from ≝
124  λA: Type[0].
125  λn.
126  λf.
127  λa.
128  λl.
129    foldi_from_until A n (|l|) f a l.
130
131definition foldi_until ≝
132  λA: Type[0].
133  λm.
134  λf.
135  λa.
136  λl.
137    foldi_from_until A 0 m f a l.
138
139definition foldi ≝
140  λA: Type[0].
141  λf.
142  λa.
143  λl.
144    foldi_from_until A 0 (|l|) f a l.
145
146definition hd_safe ≝
147  λA: Type[0].
148  λl: list A.
149  λproof: 0 < |l|.
150  match l return λx. 0 < |x| → A with
151  [ nil ⇒ λnil_absrd. ?
152  | cons hd tl ⇒ λcons_prf. hd
153  ] proof.
154  normalize in nil_absrd;
155  cases(not_le_Sn_O 0)
156  #HYP
157  cases(HYP nil_absrd)
158qed.
159
160definition tail_safe ≝
161  λA: Type[0].
162  λl: list A.
163  λproof: 0 < |l|.
164  match l return λx. 0 < |x| → list A with
165  [ nil ⇒ λnil_absrd. ?
166  | cons hd tl ⇒ λcons_prf. tl
167  ] proof.
168  normalize in nil_absrd;
169  cases(not_le_Sn_O 0)
170  #HYP
171  cases(HYP nil_absrd)
172qed.
173
174let rec safe_split
175  (A: Type[0]) (l: list A) (index: nat) (proof: index ≤ |l|)
176    on index ≝
177  match index return λx. x ≤ |l| → (list A) × (list A) with
178  [ O ⇒ λzero_prf. 〈[], l〉
179  | S index' ⇒ λsucc_prf.
180    match l return λx. S index' ≤ |x| → (list A) × (list A) with
181    [ nil ⇒ λnil_absrd. ?
182    | cons hd tl ⇒ λcons_prf.
183      let 〈l1, l2〉 ≝ safe_split A tl index' ? in
184        〈hd :: l1, l2〉
185    ] succ_prf
186  ] proof.
187  [1: normalize in nil_absrd;
188      cases(not_le_Sn_O index')
189      #HYP
190      cases(HYP nil_absrd)
191  |2: normalize in cons_prf;
192      @le_S_S_to_le
193      assumption
194  ]
195qed.
196
197let rec nth_safe
198  (elt_type: Type[0]) (index: nat) (the_list: list elt_type)
199  (proof: index < | the_list |)
200    on index ≝
201  match index return λs. s < | the_list | → elt_type with
202  [ O ⇒
203    match the_list return λt. 0 < | t | → elt_type with
204    [ nil        ⇒ λnil_absurd. ?
205    | cons hd tl ⇒ λcons_proof. hd
206    ]
207  | S index' ⇒
208    match the_list return λt. S index' < | t | → elt_type with
209    [ nil ⇒ λnil_absurd. ?
210    | cons hd tl ⇒
211      λcons_proof. nth_safe elt_type index' tl ?
212    ]
213  ] proof.
214  [ normalize in nil_absurd;
215    cases (not_le_Sn_O 0)
216    #ABSURD
217    elim (ABSURD nil_absurd)
218  | normalize in nil_absurd;
219    cases (not_le_Sn_O (S index'))
220    #ABSURD
221    elim (ABSURD nil_absurd)
222  | normalize in cons_proof;
223    @le_S_S_to_le
224    assumption
225  ]
226qed.
227
228lemma shift_nth_safe:
229 ∀T,i,l2,l1,K1,K2.
230  nth_safe T i l1 K1 = nth_safe T (i+|l2|) (l2@l1) K2.
231 #T #i #l2 elim l2 normalize
232  [ #l1 #K1 <plus_n_O #K2 %
233  | #hd #tl #IH #l1 #K1 <plus_n_Sm #K2 change with (? < ?) in K1; change with (? < ?) in K2;
234    whd in ⊢ (???%); @IH ]
235qed.
236
237lemma shift_nth_prefix:
238 ∀T,l1,i,l2,K1,K2.
239  nth_safe T i l1 K1 = nth_safe T i (l1@l2) K2.
240  #T #l1 elim l1 normalize
241  [
242    #i #l1 #K1 cases(lt_to_not_zero … K1)
243  |
244    #hd #tl #IH #i #l2
245    cases i
246    [
247      //
248    |
249      #i' #K1 #K2 whd in ⊢ (??%%);
250      @IH
251    ]
252  ]
253qed.
254
255(*CSC: practically equal to shift_nth_safe but for commutation
256  of addition. One of the two lemmas should disappear. *)
257lemma nth_safe_prepend:
258 ∀A,l1,l2,j.∀H:j<|l2|.∀K:|l1|+j<|(l1@l2)|.
259  nth_safe A j l2 H =nth_safe A (|l1|+j) (l1@l2) K.
260 #A #l1 #l2 #j #H >commutative_plus @shift_nth_safe
261qed.
262
263lemma nth_safe_cons:
264 ∀A,hd,tl,l2,j,j_ok,Sj_ok.
265  nth_safe A j (tl@l2) j_ok =nth_safe A (1+j) (hd::tl@l2) Sj_ok.
266//
267qed.
268
269lemma eq_nth_safe_proof_irrelevant:
270 ∀A,l,i,i_ok,i_ok'.
271  nth_safe A l i i_ok = nth_safe A l i i_ok'.
272#A #l #i #i_ok #i_ok' %
273qed.
274
275lemma nth_safe_append:
276 ∀A,l,n,n_ok.
277  ∃pre,suff.
278   (pre @ [nth_safe A n l n_ok]) @ suff = l.
279#A #l elim l normalize
280 [ #n #abs cases (absurd ? abs (not_le_Sn_O ?))
281 | #hd #tl #IH #n cases n normalize
282   [ #_ %{[]} /2/
283   | #m #m_ok cases (IH m ?)
284     [ #pre * #suff #EQ %{(hd::pre)} %{suff} <EQ in ⊢ (???%); % | skip ]]
285qed.
286
287definition last_safe ≝
288  λelt_type: Type[0].
289  λthe_list: list elt_type.
290  λproof   : 0 < | the_list |.
291    nth_safe elt_type (|the_list| - 1) the_list ?.
292  normalize /2 by lt_plus_to_minus/
293qed.
294
295let rec reduce
296  (A: Type[0]) (B: Type[0]) (left: list A) (right: list B) on left ≝
297  match left with
298  [ nil ⇒ 〈〈[ ], [ ]〉, 〈[ ], right〉〉
299  | cons hd tl ⇒
300    match right with
301    [ nil ⇒ 〈〈[ ], left〉, 〈[ ], [ ]〉〉
302    | cons hd' tl' ⇒
303      let 〈cleft, cright〉 ≝ reduce A B tl tl' in
304      let 〈commonl, restl〉 ≝ cleft in
305      let 〈commonr, restr〉 ≝ cright in
306        〈〈hd :: commonl, restl〉, 〈hd' :: commonr, restr〉〉
307    ]
308  ].
309
310(*
311axiom reduce_strong:
312  ∀A: Type[0].
313  ∀left: list A.
314  ∀right: list A.
315    Σret: ((list A) × (list A)) × ((list A) × (list A)). | \fst (\fst ret) | = | \fst (\snd ret) |.
316*)
317
318let rec reduce_strong
319  (A: Type[0]) (B: Type[0]) (left: list A) (right: list B)
320    on left : Σret: ((list A) × (list A)) × ((list B) × (list B)). |\fst (\fst ret)| = |\fst (\snd ret)|  ≝
321  match left with
322  [ nil ⇒ 〈〈[ ], [ ]〉, 〈[ ], right〉〉
323  | cons hd tl ⇒
324    match right with
325    [ nil ⇒ 〈〈[ ], left〉, 〈[ ], [ ]〉〉
326    | cons hd' tl' ⇒
327      let 〈cleft, cright〉 ≝ pi1 ?? (reduce_strong A B tl tl') in
328      let 〈commonl, restl〉 ≝ cleft in
329      let 〈commonr, restr〉 ≝ cright in
330        〈〈hd :: commonl, restl〉, 〈hd' :: commonr, restr〉〉
331    ]
332  ].
333  [ 1: normalize %
334  | 2: normalize %
335  | 3: normalize >p3 in p2; >p4 cases (reduce_strong … tl tl1) normalize
336       #X #H #EQ destruct // ]
337qed.
338   
339let rec map2_opt
340  (A: Type[0]) (B: Type[0]) (C: Type[0]) (f: A → B → C)
341  (left: list A) (right: list B) on left ≝
342  match left with
343  [ nil ⇒
344    match right with
345    [ nil ⇒ Some ? (nil C)
346    | _ ⇒ None ?
347    ]
348  | cons hd tl ⇒
349    match right with
350    [ nil ⇒ None ?
351    | cons hd' tl' ⇒
352      match map2_opt A B C f tl tl' with
353      [ None ⇒ None ?
354      | Some tail ⇒ Some ? (f hd hd' :: tail)
355      ]
356    ]
357  ].
358
359let rec map2
360  (A: Type[0]) (B: Type[0]) (C: Type[0]) (f: A → B → C)
361  (left: list A) (right: list B) (proof: | left | = | right |) on left ≝
362  match left return λx. | x | = | right | → list C with
363  [ nil ⇒
364    match right return λy. | [] | = | y | → list C with
365    [ nil ⇒ λnil_prf. nil C
366    | _ ⇒ λcons_absrd. ?
367    ]
368  | cons hd tl ⇒
369    match right return λy. | hd::tl | = | y | → list C with
370    [ nil ⇒ λnil_absrd. ?
371    | cons hd' tl' ⇒ λcons_prf. (f hd hd') :: map2 A B C f tl tl' ?
372    ]
373  ] proof.
374  [1: normalize in cons_absrd;
375      destruct(cons_absrd)
376  |2: normalize in nil_absrd;
377      destruct(nil_absrd)
378  |3: normalize in cons_prf;
379      destruct(cons_prf)
380      assumption
381  ]
382qed.
383
384let rec map3
385  (A: Type[0]) (B: Type[0]) (C: Type[0]) (D: Type[0]) (f: A → B → C → D)
386  (left: list A) (centre: list B) (right: list C)
387  (prflc: |left| = |centre|) (prfcr: |centre| = |right|) on left ≝
388  match left return λx. |x| = |centre| → list D with
389  [ nil ⇒ λnil_prf.
390    match centre return λx. |x| = |right| → list D with
391    [ nil ⇒ λnil_nil_prf.
392      match right return λx. |nil ?| = |x| → list D with
393      [ nil        ⇒ λnil_nil_nil_prf. nil D
394      | cons hd tl ⇒ λcons_nil_nil_absrd. ?
395      ] nil_nil_prf
396    | cons hd tl ⇒ λnil_cons_absrd. ?
397    ] prfcr
398  | cons hd tl ⇒ λcons_prf.
399    match centre return λx. |x| = |right| → list D with
400    [ nil ⇒ λcons_nil_absrd. ?
401    | cons hd' tl' ⇒ λcons_cons_prf.
402      match right return λx. |right| = |x| → |cons ? hd' tl'| = |x| → list D with
403      [ nil ⇒ λrefl_prf. λcons_cons_nil_absrd. ?
404      | cons hd'' tl'' ⇒ λrefl_prf. λcons_cons_cons_prf.
405        (f hd hd' hd'') :: (map3 A B C D f tl tl' tl'' ? ?)
406      ] (refl ? (|right|)) cons_cons_prf
407    ] prfcr
408  ] prflc.
409  [ 1: normalize in cons_nil_nil_absrd;
410       destruct(cons_nil_nil_absrd)
411  | 2: generalize in match nil_cons_absrd;
412       <prfcr <nil_prf #HYP
413       normalize in HYP;
414       destruct(HYP)
415  | 3: generalize in match cons_nil_absrd;
416       <prfcr <cons_prf #HYP
417       normalize in HYP;
418       destruct(HYP)
419  | 4: normalize in cons_cons_nil_absrd;
420       destruct(cons_cons_nil_absrd)
421  | 5: normalize in cons_cons_cons_prf;
422       destruct(cons_cons_cons_prf)
423       assumption
424  | 6: generalize in match cons_cons_cons_prf;
425       <refl_prf <prfcr <cons_prf #HYP
426       normalize in HYP;
427       destruct(HYP)
428       @sym_eq assumption
429  ]
430qed.
431 
432lemma eq_rect_Type0_r :
433  ∀A: Type[0].
434  ∀a:A.
435  ∀P: ∀x:A. eq ? x a → Type[0]. P a (refl A a) → ∀x: A.∀p:eq ? x a. P x p.
436  #A #a #P #H #x #p lapply H lapply P cases p //
437qed.
438 
439let rec safe_nth (A: Type[0]) (n: nat) (l: list A) (p: n < length A l) on n: A ≝
440  match n return λo. o < length A l → A with
441  [ O ⇒
442    match l return λm. 0 < length A m → A with
443    [ nil ⇒ λabsd1. ?
444    | cons hd tl ⇒ λprf1. hd
445    ]
446  | S n' ⇒
447    match l return λm. S n' < length A m → A with
448    [ nil ⇒ λabsd2. ?
449    | cons hd tl ⇒ λprf2. safe_nth A n' tl ?
450    ]
451  ] ?.
452  [ 1:
453    @ p
454  | 4:
455    normalize in prf2;
456    normalize
457    @ le_S_S_to_le
458    assumption
459  | 2:
460    normalize in absd1;
461    cases (not_le_Sn_O O)
462    # H
463    elim (H absd1)
464  | 3:
465    normalize in absd2;
466    cases (not_le_Sn_O (S n'))
467    # H
468    elim (H absd2)
469  ]
470qed.
471 
472let rec nub_by_internal (A: Type[0]) (f: A → A → bool) (l: list A) (n: nat) on n ≝
473  match n with
474  [ O ⇒
475    match l with
476    [ nil ⇒ [ ]
477    | cons hd tl ⇒ l
478    ]
479  | S n ⇒
480    match l with
481    [ nil ⇒ [ ]
482    | cons hd tl ⇒
483      hd :: nub_by_internal A f (filter ? (λy. notb (f y hd)) tl) n
484    ]
485  ].
486 
487definition nub_by ≝
488  λA: Type[0].
489  λf: A → A → bool.
490  λl: list A.
491    nub_by_internal A f l (length ? l).
492 
493let rec member (A: Type[0]) (eq: A → A → bool) (a: A) (l: list A) on l ≝
494  match l with
495  [ nil ⇒ false
496  | cons hd tl ⇒ orb (eq a hd) (member A eq a tl)
497  ].
498 
499let rec take (A: Type[0]) (n: nat) (l: list A) on n: list A ≝
500  match n with
501  [ O ⇒ [ ]
502  | S n ⇒
503    match l with
504    [ nil ⇒ [ ]
505    | cons hd tl ⇒ hd :: take A n tl
506    ]
507  ].
508 
509let rec drop (A: Type[0]) (n: nat) (l: list A) on n ≝
510  match n with
511  [ O ⇒ l
512  | S n ⇒
513    match l with
514    [ nil ⇒ [ ]
515    | cons hd tl ⇒ drop A n tl
516    ]
517  ].
518 
519definition list_split ≝
520  λA: Type[0].
521  λn: nat.
522  λl: list A.
523    〈take A n l, drop A n l〉.
524 
525let rec mapi_internal (A: Type[0]) (B: Type[0]) (n: nat) (f: nat → A → B)
526                      (l: list A) on l: list B ≝
527  match l with
528  [ nil ⇒ nil ?
529  | cons hd tl ⇒ (f n hd) :: (mapi_internal A B (n + 1) f tl)
530  ]. 
531
532definition mapi ≝
533  λA, B: Type[0].
534  λf: nat → A → B.
535  λl: list A.
536    mapi_internal A B 0 f l.
537
538let rec zip_pottier
539  (A: Type[0]) (B: Type[0]) (left: list A) (right: list B)
540    on left ≝
541  match left with
542  [ nil ⇒ [ ]
543  | cons hd tl ⇒
544    match right with
545    [ nil ⇒ [ ]
546    | cons hd' tl' ⇒ 〈hd, hd'〉 :: zip_pottier A B tl tl'
547    ]
548  ].
549
550let rec zip_safe
551  (A: Type[0]) (B: Type[0]) (left: list A) (right: list B) (prf: |left| = |right|)
552    on left ≝
553  match left return λx. |x| = |right| → list (A × B) with
554  [ nil ⇒ λnil_prf.
555    match right return λx. |[ ]| = |x| → list (A × B) with
556    [ nil ⇒ λnil_nil_prf. [ ]
557    | cons hd tl ⇒ λnil_cons_absrd. ?
558    ] nil_prf
559  | cons hd tl ⇒ λcons_prf.
560    match right return λx. |hd::tl| = |x| → list (A × B) with
561    [ nil ⇒ λcons_nil_absrd. ?
562    | cons hd' tl' ⇒ λcons_cons_prf. 〈hd, hd'〉 :: zip_safe A B tl tl' ?
563    ] cons_prf
564  ] prf.
565  [ 1: normalize in nil_cons_absrd;
566       destruct(nil_cons_absrd)
567  | 2: normalize in cons_nil_absrd;
568       destruct(cons_nil_absrd)
569  | 3: normalize in cons_cons_prf;
570       @injective_S
571       assumption
572  ]
573qed.
574
575let rec zip (A: Type[0]) (B: Type[0]) (l: list A) (r: list B) on l: option (list (A × B)) ≝
576  match l with
577  [ nil ⇒ Some ? (nil (A × B))
578  | cons hd tl ⇒
579    match r with
580    [ nil ⇒ None ?
581    | cons hd' tl' ⇒
582      match zip ? ? tl tl' with
583      [ None ⇒ None ?
584      | Some tail ⇒ Some ? (〈hd, hd'〉 :: tail)
585      ]
586    ]
587  ].
588
589let rec foldl (A: Type[0]) (B: Type[0]) (f: A → B → A) (a: A) (l: list B) on l ≝
590  match l with
591  [ nil ⇒ a
592  | cons hd tl ⇒ foldl A B f (f a hd) tl
593  ].
594
595lemma foldl_step:
596 ∀A:Type[0].
597  ∀B: Type[0].
598   ∀H: A → B → A.
599    ∀acc: A.
600     ∀pre: list B.
601      ∀hd:B.
602       foldl A B H acc (pre@[hd]) = (H (foldl A B H acc pre) hd).
603 #A #B #H #acc #pre generalize in match acc; -acc; elim pre
604  [ normalize; //
605  | #hd #tl #IH #acc #X normalize; @IH ]
606qed.
607
608lemma foldl_append:
609 ∀A:Type[0].
610  ∀B: Type[0].
611   ∀H: A → B → A.
612    ∀acc: A.
613     ∀suff,pre: list B.
614      foldl A B H acc (pre@suff) = (foldl A B H (foldl A B H acc pre) suff).
615 #A #B #H #acc #suff elim suff
616  [ #pre >append_nil %
617  | #hd #tl #IH #pre whd in ⊢ (???%); <(foldl_step … H ??) applyS (IH (pre@[hd])) ]
618qed.
619
620(* redirecting to library reverse *)
621definition rev ≝ reverse.
622
623lemma append_length:
624  ∀A: Type[0].
625  ∀l, r: list A.
626    |(l @ r)| = |l| + |r|.
627  #A #L #R
628  elim L
629  [ %
630  | #HD #TL #IH
631    normalize >IH %
632  ]
633qed.
634
635lemma rev_append:
636  ∀A: Type[0].
637  ∀l, r: list A.
638    rev A (l @ r) = rev A r @ rev A l.
639  #A #L #R
640  elim L
641  [ normalize >append_nil %
642  | #HD #TL normalize #IH
643    >rev_append_def
644    >rev_append_def
645    >rev_append_def
646    >append_nil
647    normalize
648    >IH
649    @associative_append
650  ]
651qed.
652
653lemma rev_length:
654  ∀A: Type[0].
655  ∀l: list A.
656    |rev A l| = |l|.
657  #A #L
658  elim L
659  [ %
660  | #HD #TL normalize #IH
661    >rev_append_def
662    >(append_length A (rev A TL) [HD])
663    normalize /2 by /
664  ]
665qed.
666
667lemma nth_append_first:
668 ∀A:Type[0].
669 ∀n:nat.∀l1,l2:list A.∀d:A.
670   n < |l1| → nth n A (l1@l2) d = nth n A l1 d.
671 #A #n #l1 #l2 #d
672 generalize in match n; -n; elim l1
673 [ normalize #k #Hk @⊥ @(absurd … Hk) @not_le_Sn_O
674 | #h #t #Hind #k normalize
675   cases k -k
676   [ #Hk normalize @refl
677   | #k #Hk normalize @(Hind k) @le_S_S_to_le @Hk
678   ] 
679 ]
680qed.
681
682lemma nth_append_second:
683 ∀A: Type[0].∀n.∀l1,l2:list A.∀d.n ≥ length A l1 ->
684  nth n A (l1@l2) d = nth (n - length A l1) A l2 d.
685 #A #n #l1 #l2 #d
686 generalize in match n; -n; elim l1
687 [ normalize #k #Hk <(minus_n_O) @refl
688 | #h #t #Hind #k normalize
689   cases k -k;
690   [ #Hk @⊥ @(absurd (S (|t|) ≤ 0)) [ @Hk | @not_le_Sn_O ]
691   | #k #Hk normalize @(Hind k) @le_S_S_to_le @Hk
692   ]
693 ]
694qed.
695
696   
697let rec fold_left_i_aux (A: Type[0]) (B: Type[0])
698                        (f: nat → A → B → A) (x: A) (i: nat) (l: list B) on l ≝
699  match l with
700    [ nil ⇒ x
701    | cons hd tl ⇒ fold_left_i_aux A B f (f i x hd) (S i) tl
702    ].
703
704definition fold_left_i ≝ λA,B,f,x. fold_left_i_aux A B f x O.
705
706notation "hvbox(t⌈o ↦ h⌉)"
707  with precedence 45
708  for @{ match (? : $o=$h) with [ refl ⇒ $t ] }.
709
710definition function_apply ≝
711  λA, B: Type[0].
712  λf: A → B.
713  λa: A.
714    f a.
715   
716notation "f break $ x"
717  left associative with precedence 99
718  for @{ 'function_apply $f $x }.
719 
720interpretation "Function application" 'function_apply f x = (function_apply ? ? f x).
721
722let rec iterate (A: Type[0]) (f: A → A) (a: A) (n: nat) on n ≝
723  match n with
724    [ O ⇒ a
725    | S o ⇒ f (iterate A f a o)
726    ].
727
728let rec division_aux (m: nat) (n : nat) (p: nat) ≝
729  match ltb n (S p) with
730    [ true ⇒ O
731    | false ⇒
732      match m with
733        [ O ⇒ O
734        | (S q) ⇒ S (division_aux q (n - (S p)) p)
735        ]
736    ].
737   
738definition division ≝
739  λm, n: nat.
740    match n with
741      [ O ⇒ S m
742      | S o ⇒ division_aux m m o
743      ].
744     
745notation "hvbox(n break ÷ m)"
746  right associative with precedence 47
747  for @{ 'division $n $m }.
748 
749interpretation "Nat division" 'division n m = (division n m).
750
751let rec modulus_aux (m: nat) (n: nat) (p: nat) ≝
752  match leb n p with
753    [ true ⇒ n
754    | false ⇒
755      match m with
756        [ O ⇒ n
757        | S o ⇒ modulus_aux o (n - (S p)) p
758        ]
759    ].
760   
761definition modulus ≝
762  λm, n: nat.
763    match n with
764      [ O ⇒ m
765      | S o ⇒ modulus_aux m m o
766      ].
767   
768notation "hvbox(n break 'mod' m)"
769  right associative with precedence 47
770  for @{ 'modulus $n $m }.
771 
772interpretation "Nat modulus" 'modulus m n = (modulus m n).
773
774definition divide_with_remainder ≝
775  λm, n: nat.
776    mk_Prod … (m ÷ n) (modulus m n).
777   
778notation "hvbox(a break ⊎ b)"
779 left associative with precedence 55
780for @{ 'disjoint_union $a $b }.
781interpretation "sum" 'disjoint_union A B = (Sum A B).
782
783theorem less_than_or_equal_monotone:
784  ∀m, n: nat.
785    m ≤ n → (S m) ≤ (S n).
786 #m #n #H
787 elim H
788 /2 by le_n, le_S/
789qed.
790
791theorem less_than_or_equal_b_complete:
792  ∀m, n: nat.
793    leb m n = false → ¬(m ≤ n).
794 #m;
795 elim m;
796 normalize
797 [ #n #H
798   destruct
799 | #y #H1 #z
800   cases z
801   normalize
802   [ #H
803     /2 by /
804   | /3 by not_le_to_not_le_S_S/
805   ]
806 ]
807qed.
808
809theorem less_than_or_equal_b_correct:
810  ∀m, n: nat.
811    leb m n = true → m ≤ n.
812 #m
813 elim m
814 //
815 #y #H1 #z
816 cases z
817 normalize
818 [ #H
819   destruct
820 | #n #H lapply (H1 … H) /2 by le_S_S/
821 ]
822qed.
823
824definition less_than_or_equal_b_elim:
825 ∀m, n: nat.
826 ∀P: bool → Type[0].
827   (m ≤ n → P true) → (¬(m ≤ n) → P false) → P (leb m n).
828 #m #n #P #H1 #H2;
829 lapply (less_than_or_equal_b_correct m n)
830 lapply (less_than_or_equal_b_complete m n)
831 cases (leb m n)
832 /3 by /
833qed.
834
835lemma lt_m_n_to_exists_o_plus_m_n:
836  ∀m, n: nat.
837    m < n → ∃o: nat. m + o = n.
838  #m #n
839  cases m
840  [1:
841    #irrelevant
842    %{n} %
843  |2:
844    #m' #lt_hyp
845    %{(n - S m')}
846    >commutative_plus in ⊢ (??%?);
847    <plus_minus_m_m
848    [1:
849      %
850    |2:
851      @lt_S_to_lt
852      assumption
853    ]
854  ]
855qed.
856
857lemma lt_O_n_to_S_pred_n_n:
858  ∀n: nat.
859    0 < n → S (pred n) = n.
860  #n
861  cases n
862  [1:
863    #absurd
864    cases(lt_to_not_zero 0 0 absurd)
865  |2:
866    #n' #lt_hyp %
867  ]
868qed.
869
870lemma exists_plus_m_n_to_exists_Sn:
871  ∀m, n: nat.
872    m < n → ∃p: nat. S p = n.
873  #m #n
874  cases m
875  [1:
876    #lt_hyp %{(pred n)}
877    @(lt_O_n_to_S_pred_n_n … lt_hyp)
878  |2:
879    #m' #lt_hyp %{(pred n)}
880    @(lt_O_n_to_S_pred_n_n)
881    @(transitive_le … (S m') …)
882    [1:
883      //
884    |2:
885      @lt_S_to_lt
886      assumption
887    ]
888  ]
889qed.
890
891lemma plus_right_monotone:
892  ∀m, n, o: nat.
893    m = n → m + o = n + o.
894  #m #n #o #refl >refl %
895qed.
896
897lemma plus_left_monotone:
898  ∀m, n, o: nat.
899    m = n → o + m = o + n.
900  #m #n #o #refl destruct %
901qed.
902
903lemma minus_plus_cancel:
904  ∀m, n : nat.
905  ∀proof: n ≤ m.
906    (m - n) + n = m.
907  #m #n #proof /2 by plus_minus/
908qed.
909
910lemma lt_to_le_to_le:
911  ∀n, m, p: nat.
912    n < m → m ≤ p → n ≤ p.
913  #n #m #p #H #H1
914  elim H
915  [1:
916    @(transitive_le n m p) /2/
917  |2:
918    /2/
919  ]
920qed.
921
922lemma eqb_decidable:
923  ∀l, r: nat.
924    (eqb l r = true) ∨ (eqb l r = false).
925  #l #r //
926qed.
927
928lemma r_Sr_and_l_r_to_Sl_r:
929  ∀r, l: nat.
930    (∃r': nat. r = S r' ∧ l = r') → S l = r.
931  #r #l #exists_hyp
932  cases exists_hyp #r'
933  #and_hyp cases and_hyp
934  #left_hyp #right_hyp
935  destruct %
936qed.
937
938lemma eqb_Sn_to_exists_n':
939  ∀m, n: nat.
940    eqb (S m) n = true → ∃n': nat. n = S n'.
941  #m #n
942  cases n
943  [1:
944    normalize #absurd
945    destruct(absurd)
946  |2:
947    #n' #_ %{n'} %
948  ]
949qed.
950
951lemma eqb_true_to_eqb_S_S_true:
952  ∀m, n: nat.
953    eqb m n = true → eqb (S m) (S n) = true.
954  #m #n normalize #assm assumption
955qed.
956
957lemma eqb_S_S_true_to_eqb_true:
958  ∀m, n: nat.
959    eqb (S m) (S n) = true → eqb m n = true.
960  #m #n normalize #assm assumption
961qed.
962
963lemma eqb_true_to_refl:
964  ∀l, r: nat.
965    eqb l r = true → l = r.
966  #l
967  elim l
968  [1:
969    #r cases r
970    [1:
971      #_ %
972    |2:
973      #l' normalize
974      #absurd destruct(absurd)
975    ]
976  |2:
977    #l' #inductive_hypothesis #r
978    #eqb_refl @r_Sr_and_l_r_to_Sl_r
979    %{(pred r)} @conj
980    [1:
981      cases (eqb_Sn_to_exists_n' … eqb_refl)
982      #r' #S_assm >S_assm %
983    |2:
984      cases (eqb_Sn_to_exists_n' … eqb_refl)
985      #r' #refl_assm destruct normalize
986      @inductive_hypothesis
987      normalize in eqb_refl; assumption
988    ]
989  ]
990qed.
991
992lemma r_O_or_exists_r_r_Sr_and_l_neq_r_to_Sl_neq_r:
993  ∀r, l: nat.
994    r = O ∨ (∃r': nat. r = S r' ∧ l ≠ r') → S l ≠ r.
995  #r #l #disj_hyp
996  cases disj_hyp
997  [1:
998    #r_O_refl destruct @nmk
999    #absurd destruct(absurd)
1000  |2:
1001    #exists_hyp cases exists_hyp #r'
1002    #conj_hyp cases conj_hyp #left_conj #right_conj
1003    destruct @nmk #S_S_refl_hyp
1004    elim right_conj #hyp @hyp //
1005  ]
1006qed.
1007
1008lemma neq_l_r_to_neq_Sl_Sr:
1009  ∀l, r: nat.
1010    l ≠ r → S l ≠ S r.
1011  #l #r #l_neq_r_assm
1012  @nmk #Sl_Sr_assm cases l_neq_r_assm
1013  #assm @assm //
1014qed.
1015
1016lemma eqb_false_to_not_refl:
1017  ∀l, r: nat.
1018    eqb l r = false → l ≠ r.
1019  #l
1020  elim l
1021  [1:
1022    #r cases r
1023    [1:
1024      normalize #absurd destruct(absurd)
1025    |2:
1026      #r' #_ @nmk
1027      #absurd destruct(absurd)
1028    ]
1029  |2:
1030    #l' #inductive_hypothesis #r
1031    cases r
1032    [1:
1033      #eqb_false_assm
1034      @r_O_or_exists_r_r_Sr_and_l_neq_r_to_Sl_neq_r
1035      @or_introl %
1036    |2:
1037      #r' #eqb_false_assm
1038      @neq_l_r_to_neq_Sl_Sr
1039      @inductive_hypothesis
1040      assumption
1041    ]
1042  ]
1043qed.
1044
1045lemma le_to_lt_or_eq:
1046  ∀m, n: nat.
1047    m ≤ n → m = n ∨ m < n.
1048  #m #n #le_hyp
1049  cases le_hyp
1050  [1:
1051    @or_introl %
1052  |2:
1053    #m' #le_hyp'
1054    @or_intror
1055    normalize
1056    @le_S_S assumption
1057  ]
1058qed.
1059
1060lemma le_neq_to_lt:
1061  ∀m, n: nat.
1062    m ≤ n → m ≠ n → m < n.
1063  #m #n #le_hyp #neq_hyp
1064  cases neq_hyp
1065  #eq_absurd_hyp
1066  generalize in match (le_to_lt_or_eq m n le_hyp);
1067  #disj_assm cases disj_assm
1068  [1:
1069    #absurd cases (eq_absurd_hyp absurd)
1070  |2:
1071    #assm assumption
1072  ]
1073qed.
1074
1075inverter nat_jmdiscr for nat.
1076
1077lemma plus_lt_to_lt:
1078  ∀m, n, o: nat.
1079    m + n < o → m < o.
1080  #m #n #o
1081  elim n
1082  [1:
1083    <(plus_n_O m) in ⊢ (% → ?);
1084    #assumption assumption
1085  |2:
1086    #n' #inductive_hypothesis
1087    <(plus_n_Sm m n') in ⊢ (% → ?);
1088    #assm @inductive_hypothesis
1089    normalize in assm; normalize
1090    /2 by lt_S_to_lt/
1091  ]
1092qed.
1093
1094include "arithmetics/div_and_mod.ma".
1095
1096lemma n_plus_1_n_to_False:
1097  ∀n: nat.
1098    n + 1 = n → False.
1099  #n elim n
1100  [1:
1101    normalize #absurd destruct(absurd)
1102  |2:
1103    #n' #inductive_hypothesis normalize
1104    #absurd @inductive_hypothesis /2 by injective_S/
1105  ]
1106qed.
1107
1108lemma one_two_times_n_to_False:
1109  ∀n: nat.
1110    1=2*n→False.
1111  #n cases n
1112  [1:
1113    normalize #absurd destruct(absurd)
1114  |2:
1115    #n' normalize #absurd
1116    lapply (injective_S … absurd) -absurd #absurd
1117    /2/
1118  ]
1119qed.
1120
1121(*
1122let rec odd_p
1123  (n: nat)
1124    on n ≝
1125  match n with
1126  [ O ⇒ False
1127  | S n' ⇒ even_p n'
1128  ]
1129and even_p
1130  (n: nat)
1131    on n ≝
1132  match n with
1133  [ O ⇒ True
1134  | S n' ⇒ odd_p n'
1135  ].
1136
1137let rec n_even_p_to_n_plus_2_even_p
1138  (n: nat)
1139    on n: even_p n → even_p (n + 2) ≝
1140  match n with
1141  [ O ⇒ ?
1142  | S n' ⇒ ?
1143  ]
1144and n_odd_p_to_n_plus_2_odd_p
1145  (n: nat)
1146    on n: odd_p n → odd_p (n + 2) ≝
1147  match n with
1148  [ O ⇒ ?
1149  | S n' ⇒ ?
1150  ].
1151  [1,3:
1152    normalize #assm assumption
1153  |2:
1154    normalize @n_odd_p_to_n_plus_2_odd_p
1155  |4:
1156    normalize @n_even_p_to_n_plus_2_even_p
1157  ]
1158qed.
1159
1160let rec two_times_n_even_p
1161  (n: nat)
1162    on n: even_p (2 * n) ≝
1163  match n with
1164  [ O ⇒ ?
1165  | S n' ⇒ ?
1166  ]
1167and two_times_n_plus_one_odd_p
1168  (n: nat)
1169    on n: odd_p ((2 * n) + 1) ≝
1170  match n with
1171  [ O ⇒ ?
1172  | S n' ⇒ ?
1173  ].
1174  [1,3:
1175    normalize @I
1176  |2:
1177    normalize
1178    >plus_n_Sm
1179    <(associative_plus n' n' 1)
1180    >(plus_n_O (n' + n'))
1181    cut(n' + n' + 0 + 1 = 2 * n' + 1)
1182    [1:
1183      //
1184    |2:
1185      #refl_assm >refl_assm
1186      @two_times_n_plus_one_odd_p     
1187    ]
1188  |4:
1189    normalize
1190    >plus_n_Sm
1191    cut(n' + (n' + 1) + 1 = (2 * n') + 2)
1192    [1:
1193      normalize /2/
1194    |2:
1195      #refl_assm >refl_assm
1196      @n_even_p_to_n_plus_2_even_p
1197      @two_times_n_even_p
1198    ]
1199  ]
1200qed.
1201
1202include alias "basics/logic.ma".
1203
1204let rec even_p_to_not_odd_p
1205  (n: nat)
1206    on n: even_p n → ¬ odd_p n ≝
1207  match n with
1208  [ O ⇒ ?
1209  | S n' ⇒ ?
1210  ]
1211and odd_p_to_not_even_p
1212  (n: nat)
1213    on n: odd_p n → ¬ even_p n ≝
1214  match n with
1215  [ O ⇒ ?
1216  | S n' ⇒ ?
1217  ].
1218  [1:
1219    normalize #_
1220    @nmk #assm assumption
1221  |3:
1222    normalize #absurd
1223    cases absurd
1224  |2:
1225    normalize
1226    @odd_p_to_not_even_p
1227  |4:
1228    normalize
1229    @even_p_to_not_odd_p
1230  ]
1231qed.
1232
1233lemma even_p_odd_p_cases:
1234  ∀n: nat.
1235    even_p n ∨ odd_p n.
1236  #n elim n
1237  [1:
1238    normalize @or_introl @I
1239  |2:
1240    #n' #inductive_hypothesis
1241    normalize
1242    cases inductive_hypothesis
1243    #assm
1244    try (@or_introl assumption)
1245    try (@or_intror assumption)
1246  ]
1247qed.
1248*)
1249
1250lemma two_times_n_plus_one_refl_two_times_n_to_False:
1251  ∀m, n: nat.
1252    2 * m + 1 = 2 * n → False.
1253@nat_elim2
1254[ * [2: #n ] normalize [ <plus_n_Sm ]
1255| #n normalize
1256| #n #m #IH >commutative_times >commutative_times in ⊢ (???%→?); normalize
1257] #EQ destruct @IH
1258>commutative_times >commutative_times in ⊢ (???%); assumption
1259qed.
1260
1261lemma not_Some_neq_None_to_False:
1262  ∀a: Type[0].
1263  ∀e: a.
1264    ¬ (Some a e ≠ None a) → False.
1265  #a #e #absurd cases absurd -absurd
1266  #absurd @absurd @nmk -absurd
1267  #absurd destruct(absurd)
1268qed.
1269
1270lemma not_None_to_Some:
1271  ∀A: Type[0].
1272  ∀o: option A.
1273    o ≠ None A → ∃v: A. o = Some A v.
1274  #A #o cases o
1275  [1:
1276    #absurd cases absurd #absurd' cases (absurd' (refl …))
1277  |2:
1278    #v' #ignore /2/
1279  ]
1280qed.
1281
1282lemma inclusive_disjunction_true:
1283  ∀b, c: bool.
1284    (orb b c) = true → b = true ∨ c = true.
1285  # b
1286  # c
1287  elim b
1288  [ normalize
1289    # H
1290    @ or_introl
1291    %
1292  | normalize
1293    /3 by trans_eq, orb_true_l/
1294  ]
1295qed.
1296
1297lemma conjunction_true:
1298  ∀b, c: bool.
1299    andb b c = true → b = true ∧ c = true.
1300  # b
1301  # c
1302  elim b
1303  normalize
1304  [ /2 by conj/
1305  | # K
1306    destruct
1307  ]
1308qed.
1309
1310lemma eq_true_false: false=true → False.
1311 # K
1312 destruct
1313qed.
1314
1315lemma inclusive_disjunction_b_true: ∀b. orb b true = true.
1316 # b
1317 cases b
1318 %
1319qed.
1320
1321(* XXX: to be moved into logic/basics.ma *)
1322lemma and_intro_right:
1323  ∀a, b: Prop.
1324    a → (a → b) → a ∧ b.
1325  #a #b /3/
1326qed.
1327
1328definition bool_to_Prop ≝
1329 λb. match b with [ true ⇒ True | false ⇒ False ].
1330
1331coercion bool_to_Prop: ∀b:bool. Prop ≝ bool_to_Prop on _b:bool to Type[0].
1332
1333lemma bool_as_Prop_to_eq : ∀b : bool. b → b = true.
1334**%
1335qed.
1336
1337(* with this you can use prf : b with b : bool with rewriting
1338   >prf rewrites b as true *)
1339coercion bool_to_Prop_to_eq : ∀b : bool.∀prf : b.b = true
1340 ≝ bool_as_Prop_to_eq on _prf : bool_to_Prop ? to (? = true).
1341
1342lemma andb_Prop : ∀b,d : bool.b → d → b∧d.
1343#b #d #btrue #dtrue >btrue >dtrue %
1344qed.
1345
1346lemma andb_Prop_true : ∀b,d : bool. (b∧d) → And (bool_to_Prop b) (bool_to_Prop d).
1347#b #d #bdtrue elim (andb_true … bdtrue) #btrue #dtrue >btrue >dtrue % %
1348qed.
1349
1350lemma orb_Prop_l : ∀b,d : bool.b → b∨d.
1351#b #d #btrue >btrue %
1352qed.
1353
1354lemma orb_Prop_r : ∀b,d : bool.d → b∨d.
1355#b #d #dtrue >dtrue elim b %
1356qed.
1357
1358lemma orb_Prop_true : ∀b,d : bool. (b∨d) → Or (bool_to_Prop b) (bool_to_Prop d).
1359#b #d #bdtrue elim (orb_true_l … bdtrue) #xtrue >xtrue [%1 | %2] %
1360qed.
1361
1362lemma notb_Prop : ∀b : bool. Not (bool_to_Prop b) → notb b.
1363* * #H [@H % | %]
1364qed.
1365
1366lemma Prop_notb : ∀b:bool. notb b → Not (bool_to_Prop b).
1367* /2/
1368qed.
1369
1370lemma not_orb : ∀b,c:bool.
1371  ¬ (b∨c) →
1372  (bool_to_Prop (¬b))∧(bool_to_Prop (¬c)).
1373* * normalize /2/
1374qed.
1375
1376lemma eq_false_to_notb: ∀b. b = false → ¬ b.
1377 *; /2 by eq_true_false, I/
1378qed.
1379
1380lemma not_b_to_eq_false : ∀b : bool. Not (bool_to_Prop b) → b = false.
1381** #H [elim (H ?) % | %]
1382qed.
1383
1384(* with this you can use prf : ¬b with b : bool with rewriting
1385   >prf rewrites b as false *)
1386coercion not_bool_to_Prop_to_eq : ∀b : bool.∀prf : Not (bool_to_Prop b).b = false
1387 ≝ not_b_to_eq_false on _prf : Not (bool_to_Prop ?) to (? = false).
1388
1389
1390lemma true_or_false_Prop : ∀b : bool.Or (bool_to_Prop b) (¬(bool_to_Prop b)).
1391* [%1 % | %2 % *]
1392qed.
1393
1394lemma eq_true_to_b : ∀b. b = true → b.
1395#b #btrue >btrue %
1396qed.
1397
1398definition if_then_else_safe : ∀A : Type[0].∀b : bool.(b → A) → (¬(bool_to_Prop b) → A) → A ≝
1399  λA,b,f,g.
1400  match b return λx.match x with [true ⇒ bool_to_Prop b | false ⇒ ¬bool_to_Prop b] → A with
1401  [ true ⇒ f
1402  | false ⇒ g
1403  ] ?. elim b % *
1404qed.
1405
1406notation > "'If' b 'then' 'with' ident prf1 'do' f 'else' 'with' ident prf2 'do' g" with precedence 46 for
1407  @{'if_then_else_safe $b (λ${ident prf1}.$f) (λ${ident prf2}.$g)}.
1408notation > "'If' b 'then' 'with' ident prf1 : ty1 'do' f 'else' 'with' ident prf2 : ty2 'do' g" with precedence 46 for
1409  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1410notation > "'If' b 'then' f 'else' 'with' ident prf2 'do' g" with precedence 46 for
1411  @{'if_then_else_safe $b (λ_.$f) (λ${ident prf2}.$g)}.
1412notation > "'If' b 'then' f 'else' 'with' ident prf2 : ty2 'do' g" with precedence 46 for
1413  @{'if_then_else_safe $b (λ_.$f) (λ${ident prf2}:$ty2.$g)}.
1414notation > "'If' b 'then' 'with' ident prf1 'do' f 'else' g" with precedence 46 for
1415  @{'if_then_else_safe $b (λ${ident prf1}.$f) (λ_.$g)}.
1416notation > "'If' b 'then' 'with' ident prf1 : ty1 'do' f 'else' g" with precedence 46 for
1417  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ_.$g)}.
1418
1419notation < "hvbox('If' \nbsp b \nbsp 'then' \nbsp break 'with' \nbsp ident prf1 : ty1 \nbsp 'do' \nbsp break f \nbsp break 'else' \nbsp break 'with' \nbsp ident prf2 : ty2 \nbsp 'do' \nbsp break g)" with precedence 46 for
1420  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1421notation < "hvbox('If' \nbsp b \nbsp 'then' \nbsp break f \nbsp break 'else' \nbsp break 'with' \nbsp ident prf2 : ty2 \nbsp 'do' \nbsp break g)" with precedence 46 for
1422  @{'if_then_else_safe $b (λ_:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1423notation < "hvbox('If' \nbsp b \nbsp 'then' \nbsp break 'with' \nbsp ident prf1 : ty1 \nbsp 'do' \nbsp break f \nbsp break 'else' \nbsp break g)" with precedence 46 for
1424  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ_:$ty2.$g)}.
1425 
1426interpretation "dependent if then else" 'if_then_else_safe b f g = (if_then_else_safe ? b f g).
1427
1428lemma If_elim : ∀A.∀P : A → Prop.∀b : bool.∀f : b → A.∀g : Not (bool_to_Prop b) → A.
1429  (∀prf.P (f prf)) → (∀prf.P (g prf)) → P (If b then with prf do f prf else with prf do g prf).
1430#A #P * #f #g #H1 #H2 normalize // qed.
1431
1432(* Also extracts an equality proof (useful when not using Russell). *)
1433notation > "hvbox('let' 〈ident x,ident y〉 'as' ident E 'return' ty ≝ t 'in' s)"
1434 with precedence 10
1435for @{ match $t return λx.∀${ident E}: x = $t. $ty with [ mk_Prod ${ident x} ${ident y} ⇒
1436        λ${ident E}.$s ] (refl ? $t) }.
1437
1438notation > "hvbox('deplet' 〈ident x,ident y〉 'as' ident E  ≝ t 'in' s)"
1439 with precedence 10
1440for @{ match $t return λx.∀${ident E}: x = $t. Σz: ?. ? with [ mk_Prod ${ident x} ${ident y} ⇒
1441        λ${ident E}.$s ] (refl ? $t) }.
1442
1443notation > "hvbox('deplet' 〈ident x,ident y,ident z〉 'as' ident E ≝ t 'in' s)"
1444 with precedence 10
1445for @{ match $t return λx.∀${fresh w}:x = $t. Σq: ?. ? with [ mk_Prod ${fresh xy} ${ident z} ⇒
1446       match ${fresh xy} return λx.∀${ident E}:? = $t. Σu: ?. ? with [ mk_Prod ${ident x} ${ident y} ⇒
1447        λ${ident E}.$s ] ] (refl ? $t) }.
1448
1449notation > "hvbox('let' 〈ident x,ident y,ident z〉 'as' ident E 'return' ty ≝ t 'in' s)"
1450 with precedence 10
1451for @{ match $t return λx.∀${fresh w}:x = $t. Σq: ?. ? with [ mk_Prod ${fresh xy} ${ident z} ⇒
1452       match ${fresh xy} return λx.∀${ident E}:? = $t. $ty with [ mk_Prod ${ident x} ${ident y} ⇒
1453        λ${ident E}.$s ] ] (refl ? $t) }.
1454
1455lemma length_append:
1456 ∀A.∀l1,l2:list A.
1457  |l1 @ l2| = |l1| + |l2|.
1458 #A #l1 elim l1
1459  [ //
1460  | #hd #tl #IH #l2 normalize <IH //]
1461qed.
1462
1463lemma nth_cons:
1464  ∀n,A,h,t,y.
1465  nth (S n) A (h::t) y = nth n A t y.
1466 #n #A #h #t #y /2 by refl/
1467qed.
1468
1469lemma option_destruct_Some: ∀A,a,b. Some A a = Some A b → a=b.
1470 #A #a #b #EQ destruct //
1471qed.
1472
1473(*CSC: just a synonim, get rid of it!*)
1474lemma Some_eq:
1475 ∀T:Type[0].∀x,y:T. Some T x = Some T y → x = y ≝ option_destruct_Some.
1476
1477lemma pi1_eq: ∀A:Type[0].∀P:A->Prop.∀s1:Σa1:A.P a1.∀s2:Σa2:A.P a2.
1478  s1 = s2 → (pi1 ?? s1) = (pi1 ?? s2).
1479 #A #P #s1 #s2 / by /
1480qed.
1481
1482lemma not_neq_None_to_eq : ∀A.∀a : option A.¬a≠None ? → a = None ?.
1483#A * [2: #a] * // #ABS elim (ABS ?) % #ABS' destruct(ABS')
1484qed.
1485
1486coercion not_neq_None : ∀A.∀a : option A.∀prf : ¬a≠None ?.a = None ? ≝
1487  not_neq_None_to_eq on _prf : ¬?≠None ? to ? = None ?.
1488
1489lemma None_Some_elim: ∀P:Prop. ∀A,a. None A = Some A a → P.
1490 #P #A #a #abs destruct
1491qed.
1492
1493discriminator Prod.
1494
1495lemma pair_replace:
1496 ∀A,B,T:Type[0].∀P:T → Prop. ∀t. ∀a,b.∀c,c': A × B. c'=c → c ≃ 〈a,b〉 →
1497  P (t a b) → P (let 〈a',b'〉 ≝ c' in t a' b').
1498 #A #B #T #P #t #a #b * #x #y * #x' #y' #H1 #H2 destruct //
1499qed.
1500
1501lemma jmpair_as_replace:
1502 ∀A,B,T:Type[0].∀P:T → Prop. ∀a:A. ∀b:B.∀c,c': A × B. ∀t: ∀a,b. c' ≃ 〈a, b〉 → T. ∀EQc: c'= c.
1503  ∀EQ:c ≃ 〈a,b〉.
1504  P (t a b ?) → P ((let 〈a',b'〉 (*as H*) ≝ c' in λH. t a' b' H) (refl_jmeq ? c')).
1505  [2:
1506    >EQc @EQ
1507  |1:
1508    #A #B #T #P #a #b
1509    #c #c' #t #EQc >EQc in t; -c' normalize #f #EQ
1510    letin eta ≝ (? : ∀ab:A × B.∀P:A × B → Type[0]. P ab → P 〈\fst ab,\snd ab〉) [2: * // ]
1511    change with (eta 〈a,b〉 (λab.c ≃ ab) EQ) in match EQ;
1512    @(jmeq_elim ?? (λab.λH.P (f (\fst ab) (\snd ab) ?) → ?) ?? EQ) normalize -eta
1513    -EQ cases c in f; normalize //
1514  ]
1515qed.
1516
1517lemma if_then_else_replace:
1518  ∀T: Type[0].
1519  ∀P: T → Prop.
1520  ∀t1, t2: T.
1521  ∀c, c', c'': bool.
1522    c' = c → c ≃ c'' → P (if c'' then t1 else t2) → P (if c' then t1 else t2).
1523  #T #P #t1 #t2 #c #c' #c'' #c_refl #c_refl' destruct #assm
1524  assumption
1525qed.
1526
1527lemma refl_to_jmrefl:
1528  ∀a: Type[0].
1529  ∀l, r: a.
1530    l = r → l ≃ r.
1531  #a #l #r #refl destruct %
1532qed.
1533
1534lemma prod_eq_left:
1535  ∀A: Type[0].
1536  ∀p, q, r: A.
1537    p = q → 〈p, r〉 = 〈q, r〉.
1538  #A #p #q #r #hyp
1539  destruct %
1540qed.
1541
1542lemma prod_eq_right:
1543  ∀A: Type[0].
1544  ∀p, q, r: A.
1545    p = q → 〈r, p〉 = 〈r, q〉.
1546  #A #p #q #r #hyp
1547  destruct %
1548qed.
1549
1550lemma destruct_bug_fix_1:
1551  ∀n: nat.
1552    S n = 0 → False.
1553  #n #absurd destruct(absurd)
1554qed.
1555
1556lemma destruct_bug_fix_2:
1557  ∀m, n: nat.
1558    S m = S n → m = n.
1559  #m #n #refl destruct %
1560qed.
1561
1562lemma eq_rect_Type1_r:
1563  ∀A: Type[1].
1564  ∀a: A.
1565  ∀P: ∀x:A. eq ? x a → Type[1]. P a (refl A a) → ∀x: A.∀p:eq ? x a. P x p.
1566  #A #a #P #H #x #p
1567  generalize in match H;
1568  generalize in match P;
1569  cases p //
1570qed.
1571
1572lemma Some_Some_elim:
1573 ∀T:Type[0].∀x,y:T.∀P:Type[2]. (x=y → P) → Some T x = Some T y → P.
1574 #T #x #y #P #H #K @H @option_destruct_Some //
1575qed.
1576
1577lemma pair_destruct_right:
1578  ∀A: Type[0].
1579  ∀B: Type[0].
1580  ∀a, c: A.
1581  ∀b, d: B.
1582    〈a, b〉 = 〈c, d〉 → b = d.
1583  #A #B #a #b #c #d //
1584qed.
1585
1586lemma pose: ∀A:Type[0].∀B:A → Type[0].∀a:A. (∀a':A. a'=a → B a') → B a.
1587  /2/
1588qed.
1589
1590definition eq_sum:
1591    ∀A, B. (A → A → bool) → (B → B → bool) → (A ⊎ B) → (A ⊎ B) → bool ≝
1592  λlt, rt, leq, req, left, right.
1593    match left with
1594    [ inl l ⇒
1595      match right with
1596      [ inl l' ⇒ leq l l'
1597      | _ ⇒ false
1598      ]
1599    | inr r ⇒
1600      match right with
1601      [ inr r' ⇒ req r r'
1602      | _ ⇒ false
1603      ]
1604    ].
1605
1606lemma eq_sum_refl:
1607  ∀A, B: Type[0].
1608  ∀leq, req.
1609  ∀s.
1610  ∀leq_refl: (∀t. leq t t = true).
1611  ∀req_refl: (∀u. req u u = true).
1612    eq_sum A B leq req s s = true.
1613  #A #B #leq #req #s #leq_refl #req_refl
1614  cases s assumption
1615qed.
1616
1617definition eq_prod: ∀A, B. (A → A → bool) → (B → B → bool) → (A × B) → (A × B) → bool ≝
1618  λlt, rt, leq, req, left, right.
1619    let 〈l, r〉 ≝ left in
1620    let 〈l', r'〉 ≝ right in
1621      leq l l' ∧ req r r'.
1622
1623lemma eq_prod_refl:
1624  ∀A, B: Type[0].
1625  ∀leq, req.
1626  ∀s.
1627  ∀leq_refl: (∀t. leq t t = true).
1628  ∀req_refl: (∀u. req u u = true).
1629    eq_prod A B leq req s s = true.
1630  #A #B #leq #req #s #leq_refl #req_refl
1631  cases s
1632  whd in ⊢ (? → ? → ??%?);
1633  #l #r
1634  >leq_refl @req_refl
1635qed.
1636 
1637lemma geb_to_leb: ∀a,b:ℕ.geb a b = leb b a.
1638  #a #b / by refl/
1639qed.
1640
1641lemma nth_last: ∀A,a,l.
1642  nth (|l|) A l a = a.
1643 #A #a #l elim l
1644 [ / by /
1645 | #h #t #Hind whd in match (nth ????); whd in match (tail ??); @Hind
1646 ]
1647qed.
1648
1649
1650lemma minus_zero_to_le: ∀n,m:ℕ.n - m = 0 → n ≤ m.
1651 #n
1652 elim n
1653 [ #m #_ @le_O_n
1654 | #n' #Hind #m cases m
1655   [ #H -n whd in match (minus ??) in H; >H @le_n
1656   | #m' -m #H whd in match (minus ??) in H; @le_S_S @Hind @H
1657   ]
1658 ]
1659qed.
1660
1661lemma plus_zero_zero: ∀n,m:ℕ.n + m = 0 → m = 0.
1662 #n #m #Hn @sym_eq @le_n_O_to_eq <Hn >commutative_plus @le_plus_n_r
1663qed.
1664
1665(* this can probably be done more simply somewhere *)
1666lemma not_true_is_false:
1667  ∀b:bool.b ≠ true → b = false.
1668 #b cases b
1669 [ #H @⊥ @(absurd ?? H) @refl
1670 | #H @refl
1671 ]
1672qed.
1673
1674(* this is in the stdlib, but commented out, why? *)
1675theorem plus_Sn_m1: ∀n,m:nat. S m + n = m + S n.
1676  #n (elim n) normalize /2 by S_pred/ qed.
1677 
1678(* these lemmas seem superfluous, but not sure how to replace them *)
1679lemma double_plus_equal: ∀a,b:ℕ.a + a = b + b → a = b.
1680 #a elim a
1681 [ normalize #b //
1682 | -a #a #Hind #b cases b [ /2 by le_n_O_to_eq/ | -b #b normalize
1683   <plus_n_Sm <plus_n_Sm #H
1684   >(Hind b (injective_S ?? (injective_S ?? H))) // ]
1685 ]
1686qed.
1687
1688lemma sth_not_s: ∀x.x ≠ S x.
1689 #x cases x
1690 [ // | #y // ]
1691qed.
1692 
1693lemma le_to_eq_plus: ∀n,z.
1694  n ≤ z → ∃k.z = n + k.
1695 #n #z elim z
1696 [ #H cases (le_to_or_lt_eq … H)
1697   [ #H2 @⊥ @(absurd … H2) @not_le_Sn_O
1698   | #H2 @(ex_intro … 0) >H2 //
1699   ]
1700 | #z' #Hind #H cases (le_to_or_lt_eq … H)
1701   [ #H' elim (Hind (le_S_S_to_le … H')) #k' #H2 @(ex_intro … (S k'))
1702     >H2 >plus_n_Sm //
1703   | #H' @(ex_intro … 0) >H' //
1704   ]
1705 ]
1706qed.
1707
1708lemma nth_safe_nth:
1709  ∀A:Type[0].∀l:list A.∀i.∀proof:i < |l|.∀x.nth_safe A i l proof = nth i A l x.
1710#A #l elim l
1711[ #i #prf @⊥ @(absurd ? prf) @le_to_not_lt @le_O_n
1712| -l #h #t #Hind #i elim i
1713  [ #prf #x normalize @refl
1714  | -i #i #Hind2 #prf #x whd in match (nth ????); whd in match (tail ??);
1715    whd in match (nth_safe ????); @Hind
1716  ]
1717]
1718qed.
1719
1720lemma flatten_singleton:
1721 ∀A,a. flatten A [a] = a.
1722#A #a normalize //
1723qed.
1724
1725lemma length_flatten_cons:
1726 ∀A,hd,tl.
1727  |flatten A (hd::tl)| = |hd| + |flatten A tl|.
1728 #A #hd #tl normalize //
1729qed.
1730
1731lemma tech_transitive_lt_3:
1732 ∀n1,n2,n3,b.
1733  n1 < b → n2 < b → n3 < b →
1734   n1 + n2 + n3 < 3 * b.
1735 #n1 #n2 #n3 #b #H1 #H2 #H3
1736 @(transitive_lt … (b + n2 + n3)) [ @monotonic_lt_plus_l @monotonic_lt_plus_l // ]
1737 @(transitive_lt … (b + b + n3)) [ @monotonic_lt_plus_l @monotonic_lt_plus_r // ]
1738 @(lt_to_le_to_lt … (b + b + b)) [ @monotonic_lt_plus_r // ] //
1739qed.
1740
1741lemma m_lt_1_to_m_refl_0:
1742  ∀m: nat.
1743    m < 1 → m = 0.
1744  #m cases m try (#irrelevant %)
1745  #m' whd in ⊢ (% → ?); #relevant
1746  lapply (le_S_S_to_le … relevant)
1747  change with (? < ? → ?) -relevant #relevant
1748  cases (lt_to_not_zero … relevant)
1749qed.
1750
1751lemma ltb_false_to_not_lt: ∀p,q:ℕ.ltb p q = false → p ≮ q.
1752  #p #q #H @leb_false_to_not_le @H
1753qed.
1754
1755lemma ltb_true_to_lt: ∀p,q:ℕ.ltb p q = true → p < q.
1756 #p #q #H @leb_true_to_le @H
1757qed.
1758 
1759lemma plus_equals_zero: ∀x,y:ℕ.x + y = x → y = 0.
1760 #x #y cases y
1761 [ #_ @refl
1762 | -y #y elim x
1763   [ <plus_O_n / by /
1764   | -x #x #Hind #H2 @Hind normalize in H2; @injective_S @H2
1765   ]
1766 ]
1767qed.
Note: See TracBrowser for help on using the repository browser.