source: src/ASM/Util.ma @ 2327

Last change on this file since 2327 was 2314, checked in by campbell, 7 years ago

Move generic definitions from recent commit to appropriate places.

File size: 41.7 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 append_nil:
636  ∀A: Type[0].
637  ∀l: list A.
638    l @ [ ] = l.
639  #A #L
640  elim L //
641qed.
642
643lemma rev_append:
644  ∀A: Type[0].
645  ∀l, r: list A.
646    rev A (l @ r) = rev A r @ rev A l.
647  #A #L #R
648  elim L
649  [ normalize >append_nil %
650  | #HD #TL normalize #IH
651    >rev_append_def
652    >rev_append_def
653    >rev_append_def
654    >append_nil
655    normalize
656    >IH
657    @associative_append
658  ]
659qed.
660
661lemma rev_length:
662  ∀A: Type[0].
663  ∀l: list A.
664    |rev A l| = |l|.
665  #A #L
666  elim L
667  [ %
668  | #HD #TL normalize #IH
669    >rev_append_def
670    >(append_length A (rev A TL) [HD])
671    normalize /2 by /
672  ]
673qed.
674
675lemma nth_append_first:
676 ∀A:Type[0].
677 ∀n:nat.∀l1,l2:list A.∀d:A.
678   n < |l1| → nth n A (l1@l2) d = nth n A l1 d.
679 #A #n #l1 #l2 #d
680 generalize in match n; -n; elim l1
681 [ normalize #k #Hk @⊥ @(absurd … Hk) @not_le_Sn_O
682 | #h #t #Hind #k normalize
683   cases k -k
684   [ #Hk normalize @refl
685   | #k #Hk normalize @(Hind k) @le_S_S_to_le @Hk
686   ] 
687 ]
688qed.
689
690lemma nth_append_second:
691 ∀A: Type[0].∀n.∀l1,l2:list A.∀d.n ≥ length A l1 ->
692  nth n A (l1@l2) d = nth (n - length A l1) A l2 d.
693 #A #n #l1 #l2 #d
694 generalize in match n; -n; elim l1
695 [ normalize #k #Hk <(minus_n_O) @refl
696 | #h #t #Hind #k normalize
697   cases k -k;
698   [ #Hk @⊥ @(absurd (S (|t|) ≤ 0)) [ @Hk | @not_le_Sn_O ]
699   | #k #Hk normalize @(Hind k) @le_S_S_to_le @Hk
700   ]
701 ]
702qed.
703
704   
705let rec fold_left_i_aux (A: Type[0]) (B: Type[0])
706                        (f: nat → A → B → A) (x: A) (i: nat) (l: list B) on l ≝
707  match l with
708    [ nil ⇒ x
709    | cons hd tl ⇒ fold_left_i_aux A B f (f i x hd) (S i) tl
710    ].
711
712definition fold_left_i ≝ λA,B,f,x. fold_left_i_aux A B f x O.
713
714notation "hvbox(t⌈o ↦ h⌉)"
715  with precedence 45
716  for @{ match (? : $o=$h) with [ refl ⇒ $t ] }.
717
718definition function_apply ≝
719  λA, B: Type[0].
720  λf: A → B.
721  λa: A.
722    f a.
723   
724notation "f break $ x"
725  left associative with precedence 99
726  for @{ 'function_apply $f $x }.
727 
728interpretation "Function application" 'function_apply f x = (function_apply ? ? f x).
729
730let rec iterate (A: Type[0]) (f: A → A) (a: A) (n: nat) on n ≝
731  match n with
732    [ O ⇒ a
733    | S o ⇒ f (iterate A f a o)
734    ].
735
736let rec division_aux (m: nat) (n : nat) (p: nat) ≝
737  match ltb n (S p) with
738    [ true ⇒ O
739    | false ⇒
740      match m with
741        [ O ⇒ O
742        | (S q) ⇒ S (division_aux q (n - (S p)) p)
743        ]
744    ].
745   
746definition division ≝
747  λm, n: nat.
748    match n with
749      [ O ⇒ S m
750      | S o ⇒ division_aux m m o
751      ].
752     
753notation "hvbox(n break ÷ m)"
754  right associative with precedence 47
755  for @{ 'division $n $m }.
756 
757interpretation "Nat division" 'division n m = (division n m).
758
759let rec modulus_aux (m: nat) (n: nat) (p: nat) ≝
760  match leb n p with
761    [ true ⇒ n
762    | false ⇒
763      match m with
764        [ O ⇒ n
765        | S o ⇒ modulus_aux o (n - (S p)) p
766        ]
767    ].
768   
769definition modulus ≝
770  λm, n: nat.
771    match n with
772      [ O ⇒ m
773      | S o ⇒ modulus_aux m m o
774      ].
775   
776notation "hvbox(n break 'mod' m)"
777  right associative with precedence 47
778  for @{ 'modulus $n $m }.
779 
780interpretation "Nat modulus" 'modulus m n = (modulus m n).
781
782definition divide_with_remainder ≝
783  λm, n: nat.
784    mk_Prod … (m ÷ n) (modulus m n).
785   
786let rec exponential (m: nat) (n: nat) on n ≝
787  match n with
788    [ O ⇒ S O
789    | S o ⇒ m * exponential m o
790    ].
791
792interpretation "Nat exponential" 'exp n m = (exponential n m).
793   
794notation "hvbox(a break ⊎ b)"
795 left associative with precedence 55
796for @{ 'disjoint_union $a $b }.
797interpretation "sum" 'disjoint_union A B = (Sum A B).
798
799theorem less_than_or_equal_monotone:
800  ∀m, n: nat.
801    m ≤ n → (S m) ≤ (S n).
802 #m #n #H
803 elim H
804 /2 by le_n, le_S/
805qed.
806
807theorem less_than_or_equal_b_complete:
808  ∀m, n: nat.
809    leb m n = false → ¬(m ≤ n).
810 #m;
811 elim m;
812 normalize
813 [ #n #H
814   destruct
815 | #y #H1 #z
816   cases z
817   normalize
818   [ #H
819     /2 by /
820   | /3 by not_le_to_not_le_S_S/
821   ]
822 ]
823qed.
824
825theorem less_than_or_equal_b_correct:
826  ∀m, n: nat.
827    leb m n = true → m ≤ n.
828 #m
829 elim m
830 //
831 #y #H1 #z
832 cases z
833 normalize
834 [ #H
835   destruct
836 | #n #H lapply (H1 … H) /2 by le_S_S/
837 ]
838qed.
839
840definition less_than_or_equal_b_elim:
841 ∀m, n: nat.
842 ∀P: bool → Type[0].
843   (m ≤ n → P true) → (¬(m ≤ n) → P false) → P (leb m n).
844 #m #n #P #H1 #H2;
845 lapply (less_than_or_equal_b_correct m n)
846 lapply (less_than_or_equal_b_complete m n)
847 cases (leb m n)
848 /3 by /
849qed.
850
851lemma lt_m_n_to_exists_o_plus_m_n:
852  ∀m, n: nat.
853    m < n → ∃o: nat. m + o = n.
854  #m #n
855  cases m
856  [1:
857    #irrelevant
858    %{n} %
859  |2:
860    #m' #lt_hyp
861    %{(n - S m')}
862    >commutative_plus in ⊢ (??%?);
863    <plus_minus_m_m
864    [1:
865      %
866    |2:
867      @lt_S_to_lt
868      assumption
869    ]
870  ]
871qed.
872
873lemma lt_O_n_to_S_pred_n_n:
874  ∀n: nat.
875    0 < n → S (pred n) = n.
876  #n
877  cases n
878  [1:
879    #absurd
880    cases(lt_to_not_zero 0 0 absurd)
881  |2:
882    #n' #lt_hyp %
883  ]
884qed.
885
886lemma exists_plus_m_n_to_exists_Sn:
887  ∀m, n: nat.
888    m < n → ∃p: nat. S p = n.
889  #m #n
890  cases m
891  [1:
892    #lt_hyp %{(pred n)}
893    @(lt_O_n_to_S_pred_n_n … lt_hyp)
894  |2:
895    #m' #lt_hyp %{(pred n)}
896    @(lt_O_n_to_S_pred_n_n)
897    @(transitive_le … (S m') …)
898    [1:
899      //
900    |2:
901      @lt_S_to_lt
902      assumption
903    ]
904  ]
905qed.
906
907lemma plus_right_monotone:
908  ∀m, n, o: nat.
909    m = n → m + o = n + o.
910  #m #n #o #refl >refl %
911qed.
912
913lemma plus_left_monotone:
914  ∀m, n, o: nat.
915    m = n → o + m = o + n.
916  #m #n #o #refl destruct %
917qed.
918
919lemma minus_plus_cancel:
920  ∀m, n : nat.
921  ∀proof: n ≤ m.
922    (m - n) + n = m.
923  #m #n #proof /2 by plus_minus/
924qed.
925
926lemma lt_to_le_to_le:
927  ∀n, m, p: nat.
928    n < m → m ≤ p → n ≤ p.
929  #n #m #p #H #H1
930  elim H
931  [1:
932    @(transitive_le n m p) /2/
933  |2:
934    /2/
935  ]
936qed.
937
938lemma eqb_decidable:
939  ∀l, r: nat.
940    (eqb l r = true) ∨ (eqb l r = false).
941  #l #r //
942qed.
943
944lemma r_Sr_and_l_r_to_Sl_r:
945  ∀r, l: nat.
946    (∃r': nat. r = S r' ∧ l = r') → S l = r.
947  #r #l #exists_hyp
948  cases exists_hyp #r'
949  #and_hyp cases and_hyp
950  #left_hyp #right_hyp
951  destruct %
952qed.
953
954lemma eqb_Sn_to_exists_n':
955  ∀m, n: nat.
956    eqb (S m) n = true → ∃n': nat. n = S n'.
957  #m #n
958  cases n
959  [1:
960    normalize #absurd
961    destruct(absurd)
962  |2:
963    #n' #_ %{n'} %
964  ]
965qed.
966
967lemma eqb_true_to_eqb_S_S_true:
968  ∀m, n: nat.
969    eqb m n = true → eqb (S m) (S n) = true.
970  #m #n normalize #assm assumption
971qed.
972
973lemma eqb_S_S_true_to_eqb_true:
974  ∀m, n: nat.
975    eqb (S m) (S n) = true → eqb m n = true.
976  #m #n normalize #assm assumption
977qed.
978
979lemma eqb_true_to_refl:
980  ∀l, r: nat.
981    eqb l r = true → l = r.
982  #l
983  elim l
984  [1:
985    #r cases r
986    [1:
987      #_ %
988    |2:
989      #l' normalize
990      #absurd destruct(absurd)
991    ]
992  |2:
993    #l' #inductive_hypothesis #r
994    #eqb_refl @r_Sr_and_l_r_to_Sl_r
995    %{(pred r)} @conj
996    [1:
997      cases (eqb_Sn_to_exists_n' … eqb_refl)
998      #r' #S_assm >S_assm %
999    |2:
1000      cases (eqb_Sn_to_exists_n' … eqb_refl)
1001      #r' #refl_assm destruct normalize
1002      @inductive_hypothesis
1003      normalize in eqb_refl; assumption
1004    ]
1005  ]
1006qed.
1007
1008lemma r_O_or_exists_r_r_Sr_and_l_neq_r_to_Sl_neq_r:
1009  ∀r, l: nat.
1010    r = O ∨ (∃r': nat. r = S r' ∧ l ≠ r') → S l ≠ r.
1011  #r #l #disj_hyp
1012  cases disj_hyp
1013  [1:
1014    #r_O_refl destruct @nmk
1015    #absurd destruct(absurd)
1016  |2:
1017    #exists_hyp cases exists_hyp #r'
1018    #conj_hyp cases conj_hyp #left_conj #right_conj
1019    destruct @nmk #S_S_refl_hyp
1020    elim right_conj #hyp @hyp //
1021  ]
1022qed.
1023
1024lemma neq_l_r_to_neq_Sl_Sr:
1025  ∀l, r: nat.
1026    l ≠ r → S l ≠ S r.
1027  #l #r #l_neq_r_assm
1028  @nmk #Sl_Sr_assm cases l_neq_r_assm
1029  #assm @assm //
1030qed.
1031
1032lemma eqb_false_to_not_refl:
1033  ∀l, r: nat.
1034    eqb l r = false → l ≠ r.
1035  #l
1036  elim l
1037  [1:
1038    #r cases r
1039    [1:
1040      normalize #absurd destruct(absurd)
1041    |2:
1042      #r' #_ @nmk
1043      #absurd destruct(absurd)
1044    ]
1045  |2:
1046    #l' #inductive_hypothesis #r
1047    cases r
1048    [1:
1049      #eqb_false_assm
1050      @r_O_or_exists_r_r_Sr_and_l_neq_r_to_Sl_neq_r
1051      @or_introl %
1052    |2:
1053      #r' #eqb_false_assm
1054      @neq_l_r_to_neq_Sl_Sr
1055      @inductive_hypothesis
1056      assumption
1057    ]
1058  ]
1059qed.
1060
1061lemma le_to_lt_or_eq:
1062  ∀m, n: nat.
1063    m ≤ n → m = n ∨ m < n.
1064  #m #n #le_hyp
1065  cases le_hyp
1066  [1:
1067    @or_introl %
1068  |2:
1069    #m' #le_hyp'
1070    @or_intror
1071    normalize
1072    @le_S_S assumption
1073  ]
1074qed.
1075
1076lemma le_neq_to_lt:
1077  ∀m, n: nat.
1078    m ≤ n → m ≠ n → m < n.
1079  #m #n #le_hyp #neq_hyp
1080  cases neq_hyp
1081  #eq_absurd_hyp
1082  generalize in match (le_to_lt_or_eq m n le_hyp);
1083  #disj_assm cases disj_assm
1084  [1:
1085    #absurd cases (eq_absurd_hyp absurd)
1086  |2:
1087    #assm assumption
1088  ]
1089qed.
1090
1091inverter nat_jmdiscr for nat.
1092
1093lemma plus_lt_to_lt:
1094  ∀m, n, o: nat.
1095    m + n < o → m < o.
1096  #m #n #o
1097  elim n
1098  [1:
1099    <(plus_n_O m) in ⊢ (% → ?);
1100    #assumption assumption
1101  |2:
1102    #n' #inductive_hypothesis
1103    <(plus_n_Sm m n') in ⊢ (% → ?);
1104    #assm @inductive_hypothesis
1105    normalize in assm; normalize
1106    /2 by lt_S_to_lt/
1107  ]
1108qed.
1109
1110include "arithmetics/div_and_mod.ma".
1111
1112lemma n_plus_1_n_to_False:
1113  ∀n: nat.
1114    n + 1 = n → False.
1115  #n elim n
1116  [1:
1117    normalize #absurd destruct(absurd)
1118  |2:
1119    #n' #inductive_hypothesis normalize
1120    #absurd @inductive_hypothesis /2 by injective_S/
1121  ]
1122qed.
1123
1124lemma one_two_times_n_to_False:
1125  ∀n: nat.
1126    1=2*n→False.
1127  #n cases n
1128  [1:
1129    normalize #absurd destruct(absurd)
1130  |2:
1131    #n' normalize #absurd
1132    lapply (injective_S … absurd) -absurd #absurd
1133    /2/
1134  ]
1135qed.
1136
1137let rec odd_p
1138  (n: nat)
1139    on n ≝
1140  match n with
1141  [ O ⇒ False
1142  | S n' ⇒ even_p n'
1143  ]
1144and even_p
1145  (n: nat)
1146    on n ≝
1147  match n with
1148  [ O ⇒ True
1149  | S n' ⇒ odd_p n'
1150  ].
1151
1152let rec n_even_p_to_n_plus_2_even_p
1153  (n: nat)
1154    on n: even_p n → even_p (n + 2) ≝
1155  match n with
1156  [ O ⇒ ?
1157  | S n' ⇒ ?
1158  ]
1159and n_odd_p_to_n_plus_2_odd_p
1160  (n: nat)
1161    on n: odd_p n → odd_p (n + 2) ≝
1162  match n with
1163  [ O ⇒ ?
1164  | S n' ⇒ ?
1165  ].
1166  [1,3:
1167    normalize #assm assumption
1168  |2:
1169    normalize @n_odd_p_to_n_plus_2_odd_p
1170  |4:
1171    normalize @n_even_p_to_n_plus_2_even_p
1172  ]
1173qed.
1174
1175let rec two_times_n_even_p
1176  (n: nat)
1177    on n: even_p (2 * n) ≝
1178  match n with
1179  [ O ⇒ ?
1180  | S n' ⇒ ?
1181  ]
1182and two_times_n_plus_one_odd_p
1183  (n: nat)
1184    on n: odd_p ((2 * n) + 1) ≝
1185  match n with
1186  [ O ⇒ ?
1187  | S n' ⇒ ?
1188  ].
1189  [1,3:
1190    normalize @I
1191  |2:
1192    normalize
1193    >plus_n_Sm
1194    <(associative_plus n' n' 1)
1195    >(plus_n_O (n' + n'))
1196    cut(n' + n' + 0 + 1 = 2 * n' + 1)
1197    [1:
1198      //
1199    |2:
1200      #refl_assm >refl_assm
1201      @two_times_n_plus_one_odd_p     
1202    ]
1203  |4:
1204    normalize
1205    >plus_n_Sm
1206    cut(n' + (n' + 1) + 1 = (2 * n') + 2)
1207    [1:
1208      normalize /2/
1209    |2:
1210      #refl_assm >refl_assm
1211      @n_even_p_to_n_plus_2_even_p
1212      @two_times_n_even_p
1213    ]
1214  ]
1215qed.
1216
1217include alias "basics/logic.ma".
1218
1219let rec even_p_to_not_odd_p
1220  (n: nat)
1221    on n: even_p n → ¬ odd_p n ≝
1222  match n with
1223  [ O ⇒ ?
1224  | S n' ⇒ ?
1225  ]
1226and odd_p_to_not_even_p
1227  (n: nat)
1228    on n: odd_p n → ¬ even_p n ≝
1229  match n with
1230  [ O ⇒ ?
1231  | S n' ⇒ ?
1232  ].
1233  [1:
1234    normalize #_
1235    @nmk #assm assumption
1236  |3:
1237    normalize #absurd
1238    cases absurd
1239  |2:
1240    normalize
1241    @odd_p_to_not_even_p
1242  |4:
1243    normalize
1244    @even_p_to_not_odd_p
1245  ]
1246qed.
1247
1248lemma even_p_odd_p_cases:
1249  ∀n: nat.
1250    even_p n ∨ odd_p n.
1251  #n elim n
1252  [1:
1253    normalize @or_introl @I
1254  |2:
1255    #n' #inductive_hypothesis
1256    normalize
1257    cases inductive_hypothesis
1258    #assm
1259    try (@or_introl assumption)
1260    try (@or_intror assumption)
1261  ]
1262qed.
1263
1264lemma two_times_n_plus_one_refl_two_times_n_to_False:
1265  ∀m, n: nat.
1266    2 * m + 1 = 2 * n → False.
1267  #m #n
1268  #assm
1269  cut (even_p (2 * n) ∧ even_p ((2 * m) + 1))
1270  [1:
1271    >assm
1272    @conj
1273    @two_times_n_even_p
1274  |2:
1275    * #_ #absurd
1276    cases (even_p_to_not_odd_p … absurd)
1277    #assm @assm
1278    @two_times_n_plus_one_odd_p
1279  ]
1280qed.
1281
1282lemma not_Some_neq_None_to_False:
1283  ∀a: Type[0].
1284  ∀e: a.
1285    ¬ (Some a e ≠ None a) → False.
1286  #a #e #absurd cases absurd -absurd
1287  #absurd @absurd @nmk -absurd
1288  #absurd destruct(absurd)
1289qed.
1290
1291lemma not_None_to_Some:
1292  ∀A: Type[0].
1293  ∀o: option A.
1294    o ≠ None A → ∃v: A. o = Some A v.
1295  #A #o cases o
1296  [1:
1297    #absurd cases absurd #absurd' cases (absurd' (refl …))
1298  |2:
1299    #v' #ignore /2/
1300  ]
1301qed.
1302
1303lemma inclusive_disjunction_true:
1304  ∀b, c: bool.
1305    (orb b c) = true → b = true ∨ c = true.
1306  # b
1307  # c
1308  elim b
1309  [ normalize
1310    # H
1311    @ or_introl
1312    %
1313  | normalize
1314    /3 by trans_eq, orb_true_l/
1315  ]
1316qed.
1317
1318lemma conjunction_true:
1319  ∀b, c: bool.
1320    andb b c = true → b = true ∧ c = true.
1321  # b
1322  # c
1323  elim b
1324  normalize
1325  [ /2 by conj/
1326  | # K
1327    destruct
1328  ]
1329qed.
1330
1331lemma eq_true_false: false=true → False.
1332 # K
1333 destruct
1334qed.
1335
1336lemma inclusive_disjunction_b_true: ∀b. orb b true = true.
1337 # b
1338 cases b
1339 %
1340qed.
1341
1342(* XXX: to be moved into logic/basics.ma *)
1343lemma and_intro_right:
1344  ∀a, b: Prop.
1345    a → (a → b) → a ∧ b.
1346  #a #b /3/
1347qed.
1348
1349definition bool_to_Prop ≝
1350 λb. match b with [ true ⇒ True | false ⇒ False ].
1351
1352coercion bool_to_Prop: ∀b:bool. Prop ≝ bool_to_Prop on _b:bool to Type[0].
1353
1354lemma bool_as_Prop_to_eq : ∀b : bool. b → b = true.
1355**%
1356qed.
1357
1358(* with this you can use prf : b with b : bool with rewriting
1359   >prf rewrites b as true *)
1360coercion bool_to_Prop_to_eq : ∀b : bool.∀prf : b.b = true
1361 ≝ bool_as_Prop_to_eq on _prf : bool_to_Prop ? to (? = true).
1362
1363lemma andb_Prop : ∀b,d : bool.b → d → b∧d.
1364#b #d #btrue #dtrue >btrue >dtrue %
1365qed.
1366
1367lemma andb_Prop_true : ∀b,d : bool. (b∧d) → And (bool_to_Prop b) (bool_to_Prop d).
1368#b #d #bdtrue elim (andb_true … bdtrue) #btrue #dtrue >btrue >dtrue % %
1369qed.
1370
1371lemma orb_Prop_l : ∀b,d : bool.b → b∨d.
1372#b #d #btrue >btrue %
1373qed.
1374
1375lemma orb_Prop_r : ∀b,d : bool.d → b∨d.
1376#b #d #dtrue >dtrue elim b %
1377qed.
1378
1379lemma orb_Prop_true : ∀b,d : bool. (b∨d) → Or (bool_to_Prop b) (bool_to_Prop d).
1380#b #d #bdtrue elim (orb_true_l … bdtrue) #xtrue >xtrue [%1 | %2] %
1381qed.
1382
1383lemma notb_Prop : ∀b : bool. Not (bool_to_Prop b) → notb b.
1384* * #H [@H % | %]
1385qed.
1386
1387lemma Prop_notb : ∀b:bool. notb b → Not (bool_to_Prop b).
1388* /2/
1389qed.
1390
1391lemma not_orb : ∀b,c:bool.
1392  ¬ (b∨c) →
1393  (bool_to_Prop (¬b))∧(bool_to_Prop (¬c)).
1394* * normalize /2/
1395qed.
1396
1397lemma eq_false_to_notb: ∀b. b = false → ¬ b.
1398 *; /2 by eq_true_false, I/
1399qed.
1400
1401lemma not_b_to_eq_false : ∀b : bool. Not (bool_to_Prop b) → b = false.
1402** #H [elim (H ?) % | %]
1403qed.
1404
1405(* with this you can use prf : ¬b with b : bool with rewriting
1406   >prf rewrites b as false *)
1407coercion not_bool_to_Prop_to_eq : ∀b : bool.∀prf : Not (bool_to_Prop b).b = false
1408 ≝ not_b_to_eq_false on _prf : Not (bool_to_Prop ?) to (? = false).
1409
1410
1411lemma true_or_false_Prop : ∀b : bool.Or (bool_to_Prop b) (¬(bool_to_Prop b)).
1412* [%1 % | %2 % *]
1413qed.
1414
1415lemma eq_true_to_b : ∀b. b = true → b.
1416#b #btrue >btrue %
1417qed.
1418
1419definition if_then_else_safe : ∀A : Type[0].∀b : bool.(b → A) → (¬(bool_to_Prop b) → A) → A ≝
1420  λA,b,f,g.
1421  match b return λx.match x with [true ⇒ bool_to_Prop b | false ⇒ ¬bool_to_Prop b] → A with
1422  [ true ⇒ f
1423  | false ⇒ g
1424  ] ?. elim b % *
1425qed.
1426
1427notation > "'If' b 'then' 'with' ident prf1 'do' f 'else' 'with' ident prf2 'do' g" with precedence 46 for
1428  @{'if_then_else_safe $b (λ${ident prf1}.$f) (λ${ident prf2}.$g)}.
1429notation > "'If' b 'then' 'with' ident prf1 : ty1 'do' f 'else' 'with' ident prf2 : ty2 'do' g" with precedence 46 for
1430  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1431notation > "'If' b 'then' f 'else' 'with' ident prf2 'do' g" with precedence 46 for
1432  @{'if_then_else_safe $b (λ_.$f) (λ${ident prf2}.$g)}.
1433notation > "'If' b 'then' f 'else' 'with' ident prf2 : ty2 'do' g" with precedence 46 for
1434  @{'if_then_else_safe $b (λ_.$f) (λ${ident prf2}:$ty2.$g)}.
1435notation > "'If' b 'then' 'with' ident prf1 'do' f 'else' g" with precedence 46 for
1436  @{'if_then_else_safe $b (λ${ident prf1}.$f) (λ_.$g)}.
1437notation > "'If' b 'then' 'with' ident prf1 : ty1 'do' f 'else' g" with precedence 46 for
1438  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ_.$g)}.
1439
1440notation < "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
1441  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1442notation < "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
1443  @{'if_then_else_safe $b (λ_:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1444notation < "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
1445  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ_:$ty2.$g)}.
1446 
1447interpretation "dependent if then else" 'if_then_else_safe b f g = (if_then_else_safe ? b f g).
1448
1449lemma If_elim : ∀A.∀P : A → Prop.∀b : bool.∀f : b → A.∀g : Not (bool_to_Prop b) → A.
1450  (∀prf.P (f prf)) → (∀prf.P (g prf)) → P (If b then with prf do f prf else with prf do g prf).
1451#A #P * #f #g #H1 #H2 normalize // qed.
1452
1453(* Also extracts an equality proof (useful when not using Russell). *)
1454notation > "hvbox('let' 〈ident x,ident y〉 'as' ident E 'return' ty ≝ t 'in' s)"
1455 with precedence 10
1456for @{ match $t return λx.∀${ident E}: x = $t. $ty with [ mk_Prod ${ident x} ${ident y} ⇒
1457        λ${ident E}.$s ] (refl ? $t) }.
1458
1459notation > "hvbox('deplet' 〈ident x,ident y〉 'as' ident E  ≝ t 'in' s)"
1460 with precedence 10
1461for @{ match $t return λx.∀${ident E}: x = $t. Σz: ?. ? with [ mk_Prod ${ident x} ${ident y} ⇒
1462        λ${ident E}.$s ] (refl ? $t) }.
1463
1464notation > "hvbox('deplet' 〈ident x,ident y,ident z〉 'as' ident E ≝ t 'in' s)"
1465 with precedence 10
1466for @{ match $t return λx.∀${fresh w}:x = $t. Σq: ?. ? with [ mk_Prod ${fresh xy} ${ident z} ⇒
1467       match ${fresh xy} return λx.∀${ident E}:? = $t. Σu: ?. ? with [ mk_Prod ${ident x} ${ident y} ⇒
1468        λ${ident E}.$s ] ] (refl ? $t) }.
1469
1470notation > "hvbox('let' 〈ident x,ident y,ident z〉 'as' ident E 'return' ty ≝ t 'in' s)"
1471 with precedence 10
1472for @{ match $t return λx.∀${fresh w}:x = $t. Σq: ?. ? with [ mk_Prod ${fresh xy} ${ident z} ⇒
1473       match ${fresh xy} return λx.∀${ident E}:? = $t. $ty with [ mk_Prod ${ident x} ${ident y} ⇒
1474        λ${ident E}.$s ] ] (refl ? $t) }.
1475
1476lemma length_append:
1477 ∀A.∀l1,l2:list A.
1478  |l1 @ l2| = |l1| + |l2|.
1479 #A #l1 elim l1
1480  [ //
1481  | #hd #tl #IH #l2 normalize <IH //]
1482qed.
1483
1484lemma nth_cons:
1485  ∀n,A,h,t,y.
1486  nth (S n) A (h::t) y = nth n A t y.
1487 #n #A #h #t #y /2 by refl/
1488qed.
1489
1490lemma option_destruct_Some: ∀A,a,b. Some A a = Some A b → a=b.
1491 #A #a #b #EQ destruct //
1492qed.
1493
1494(*CSC: just a synonim, get rid of it!*)
1495lemma Some_eq:
1496 ∀T:Type[0].∀x,y:T. Some T x = Some T y → x = y ≝ option_destruct_Some.
1497
1498lemma pi1_eq: ∀A:Type[0].∀P:A->Prop.∀s1:Σa1:A.P a1.∀s2:Σa2:A.P a2.
1499  s1 = s2 → (pi1 ?? s1) = (pi1 ?? s2).
1500 #A #P #s1 #s2 / by /
1501qed.
1502
1503lemma not_neq_None_to_eq : ∀A.∀a : option A.¬a≠None ? → a = None ?.
1504#A * [2: #a] * // #ABS elim (ABS ?) % #ABS' destruct(ABS')
1505qed.
1506
1507coercion not_neq_None : ∀A.∀a : option A.∀prf : ¬a≠None ?.a = None ? ≝
1508  not_neq_None_to_eq on _prf : ¬?≠None ? to ? = None ?.
1509
1510lemma None_Some_elim: ∀P:Prop. ∀A,a. None A = Some A a → P.
1511 #P #A #a #abs destruct
1512qed.
1513
1514discriminator Prod.
1515
1516lemma pair_replace:
1517 ∀A,B,T:Type[0].∀P:T → Prop. ∀t. ∀a,b.∀c,c': A × B. c'=c → c ≃ 〈a,b〉 →
1518  P (t a b) → P (let 〈a',b'〉 ≝ c' in t a' b').
1519 #A #B #T #P #t #a #b * #x #y * #x' #y' #H1 #H2 destruct //
1520qed.
1521
1522lemma jmpair_as_replace:
1523 ∀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.
1524  ∀EQ:c ≃ 〈a,b〉.
1525  P (t a b ?) → P ((let 〈a',b'〉 (*as H*) ≝ c' in λH. t a' b' H) (refl_jmeq ? c')).
1526  [2:
1527    >EQc @EQ
1528  |1:
1529    #A #B #T #P #a #b
1530    #c #c' #t #EQc >EQc in t; -c' normalize #f #EQ
1531    letin eta ≝ (? : ∀ab:A × B.∀P:A × B → Type[0]. P ab → P 〈\fst ab,\snd ab〉) [2: * // ]
1532    change with (eta 〈a,b〉 (λab.c ≃ ab) EQ) in match EQ;
1533    @(jmeq_elim ?? (λab.λH.P (f (\fst ab) (\snd ab) ?) → ?) ?? EQ) normalize -eta
1534    -EQ cases c in f; normalize //
1535  ]
1536qed.
1537
1538lemma if_then_else_replace:
1539  ∀T: Type[0].
1540  ∀P: T → Prop.
1541  ∀t1, t2: T.
1542  ∀c, c', c'': bool.
1543    c' = c → c ≃ c'' → P (if c'' then t1 else t2) → P (if c' then t1 else t2).
1544  #T #P #t1 #t2 #c #c' #c'' #c_refl #c_refl' destruct #assm
1545  assumption
1546qed.
1547
1548lemma refl_to_jmrefl:
1549  ∀a: Type[0].
1550  ∀l, r: a.
1551    l = r → l ≃ r.
1552  #a #l #r #refl destruct %
1553qed.
1554
1555lemma prod_eq_left:
1556  ∀A: Type[0].
1557  ∀p, q, r: A.
1558    p = q → 〈p, r〉 = 〈q, r〉.
1559  #A #p #q #r #hyp
1560  destruct %
1561qed.
1562
1563lemma prod_eq_right:
1564  ∀A: Type[0].
1565  ∀p, q, r: A.
1566    p = q → 〈r, p〉 = 〈r, q〉.
1567  #A #p #q #r #hyp
1568  destruct %
1569qed.
1570
1571lemma destruct_bug_fix_1:
1572  ∀n: nat.
1573    S n = 0 → False.
1574  #n #absurd destruct(absurd)
1575qed.
1576
1577lemma destruct_bug_fix_2:
1578  ∀m, n: nat.
1579    S m = S n → m = n.
1580  #m #n #refl destruct %
1581qed.
1582
1583lemma eq_rect_Type1_r:
1584  ∀A: Type[1].
1585  ∀a: A.
1586  ∀P: ∀x:A. eq ? x a → Type[1]. P a (refl A a) → ∀x: A.∀p:eq ? x a. P x p.
1587  #A #a #P #H #x #p
1588  generalize in match H;
1589  generalize in match P;
1590  cases p //
1591qed.
1592
1593lemma Some_Some_elim:
1594 ∀T:Type[0].∀x,y:T.∀P:Type[2]. (x=y → P) → Some T x = Some T y → P.
1595 #T #x #y #P #H #K @H @option_destruct_Some //
1596qed.
1597
1598lemma pair_destruct_right:
1599  ∀A: Type[0].
1600  ∀B: Type[0].
1601  ∀a, c: A.
1602  ∀b, d: B.
1603    〈a, b〉 = 〈c, d〉 → b = d.
1604  #A #B #a #b #c #d //
1605qed.
1606
1607lemma pose: ∀A:Type[0].∀B:A → Type[0].∀a:A. (∀a':A. a'=a → B a') → B a.
1608  /2/
1609qed.
1610
1611definition eq_sum:
1612    ∀A, B. (A → A → bool) → (B → B → bool) → (A ⊎ B) → (A ⊎ B) → bool ≝
1613  λlt, rt, leq, req, left, right.
1614    match left with
1615    [ inl l ⇒
1616      match right with
1617      [ inl l' ⇒ leq l l'
1618      | _ ⇒ false
1619      ]
1620    | inr r ⇒
1621      match right with
1622      [ inr r' ⇒ req r r'
1623      | _ ⇒ false
1624      ]
1625    ].
1626
1627lemma eq_sum_refl:
1628  ∀A, B: Type[0].
1629  ∀leq, req.
1630  ∀s.
1631  ∀leq_refl: (∀t. leq t t = true).
1632  ∀req_refl: (∀u. req u u = true).
1633    eq_sum A B leq req s s = true.
1634  #A #B #leq #req #s #leq_refl #req_refl
1635  cases s assumption
1636qed.
1637
1638definition eq_prod: ∀A, B. (A → A → bool) → (B → B → bool) → (A × B) → (A × B) → bool ≝
1639  λlt, rt, leq, req, left, right.
1640    let 〈l, r〉 ≝ left in
1641    let 〈l', r'〉 ≝ right in
1642      leq l l' ∧ req r r'.
1643
1644lemma eq_prod_refl:
1645  ∀A, B: Type[0].
1646  ∀leq, req.
1647  ∀s.
1648  ∀leq_refl: (∀t. leq t t = true).
1649  ∀req_refl: (∀u. req u u = true).
1650    eq_prod A B leq req s s = true.
1651  #A #B #leq #req #s #leq_refl #req_refl
1652  cases s
1653  whd in ⊢ (? → ? → ??%?);
1654  #l #r
1655  >leq_refl @req_refl
1656qed.
1657 
1658lemma geb_to_leb: ∀a,b:ℕ.geb a b = leb b a.
1659  #a #b / by refl/
1660qed.
1661
1662lemma nth_last: ∀A,a,l.
1663  nth (|l|) A l a = a.
1664 #A #a #l elim l
1665 [ / by /
1666 | #h #t #Hind whd in match (nth ????); whd in match (tail ??); @Hind
1667 ]
1668qed.
1669
1670
1671lemma minus_zero_to_le: ∀n,m:ℕ.n - m = 0 → n ≤ m.
1672 #n
1673 elim n
1674 [ #m #_ @le_O_n
1675 | #n' #Hind #m cases m
1676   [ #H -n whd in match (minus ??) in H; >H @le_n
1677   | #m' -m #H whd in match (minus ??) in H; @le_S_S @Hind @H
1678   ]
1679 ]
1680qed.
1681
1682lemma plus_zero_zero: ∀n,m:ℕ.n + m = 0 → m = 0.
1683 #n #m #Hn @sym_eq @le_n_O_to_eq <Hn >commutative_plus @le_plus_n_r
1684qed.
1685
1686(* this can probably be done more simply somewhere *)
1687lemma not_true_is_false:
1688  ∀b:bool.b ≠ true → b = false.
1689 #b cases b
1690 [ #H @⊥ @(absurd ?? H) @refl
1691 | #H @refl
1692 ]
1693qed.
1694
1695(* this is in the stdlib, but commented out, why? *)
1696theorem plus_Sn_m1: ∀n,m:nat. S m + n = m + S n.
1697  #n (elim n) normalize /2 by S_pred/ qed.
1698 
1699(* these lemmas seem superfluous, but not sure how to replace them *)
1700lemma double_plus_equal: ∀a,b:ℕ.a + a = b + b → a = b.
1701 #a elim a
1702 [ normalize #b //
1703 | -a #a #Hind #b cases b [ /2 by le_n_O_to_eq/ | -b #b normalize
1704   <plus_n_Sm <plus_n_Sm #H
1705   >(Hind b (injective_S ?? (injective_S ?? H))) // ]
1706 ]
1707qed.
1708
1709lemma sth_not_s: ∀x.x ≠ S x.
1710 #x cases x
1711 [ // | #y // ]
1712qed.
1713 
1714lemma le_to_eq_plus: ∀n,z.
1715  n ≤ z → ∃k.z = n + k.
1716 #n #z elim z
1717 [ #H cases (le_to_or_lt_eq … H)
1718   [ #H2 @⊥ @(absurd … H2) @not_le_Sn_O
1719   | #H2 @(ex_intro … 0) >H2 //
1720   ]
1721 | #z' #Hind #H cases (le_to_or_lt_eq … H)
1722   [ #H' elim (Hind (le_S_S_to_le … H')) #k' #H2 @(ex_intro … (S k'))
1723     >H2 >plus_n_Sm //
1724   | #H' @(ex_intro … 0) >H' //
1725   ]
1726 ]
1727qed.
1728
1729lemma nth_safe_nth:
1730  ∀A:Type[0].∀l:list A.∀i.∀proof:i < |l|.∀x.nth_safe A i l proof = nth i A l x.
1731#A #l elim l
1732[ #i #prf @⊥ @(absurd ? prf) @le_to_not_lt @le_O_n
1733| -l #h #t #Hind #i elim i
1734  [ #prf #x normalize @refl
1735  | -i #i #Hind2 #prf #x whd in match (nth ????); whd in match (tail ??);
1736    whd in match (nth_safe ????); @Hind
1737  ]
1738]
1739qed.
1740
1741lemma flatten_singleton:
1742 ∀A,a. flatten A [a] = a.
1743#A #a normalize //
1744qed.
1745
1746lemma length_flatten_cons:
1747 ∀A,hd,tl.
1748  |flatten A (hd::tl)| = |hd| + |flatten A tl|.
1749 #A #hd #tl normalize //
1750qed.
1751
1752lemma tech_transitive_lt_3:
1753 ∀n1,n2,n3,b.
1754  n1 < b → n2 < b → n3 < b →
1755   n1 + n2 + n3 < 3 * b.
1756 #n1 #n2 #n3 #b #H1 #H2 #H3
1757 @(transitive_lt … (b + n2 + n3)) [ @monotonic_lt_plus_l @monotonic_lt_plus_l // ]
1758 @(transitive_lt … (b + b + n3)) [ @monotonic_lt_plus_l @monotonic_lt_plus_r // ]
1759 @(lt_to_le_to_lt … (b + b + b)) [ @monotonic_lt_plus_r // ] //
1760qed.
1761
1762lemma m_lt_1_to_m_refl_0:
1763  ∀m: nat.
1764    m < 1 → m = 0.
1765  #m cases m try (#irrelevant %)
1766  #m' whd in ⊢ (% → ?); #relevant
1767  lapply (le_S_S_to_le … relevant)
1768  change with (? < ? → ?) -relevant #relevant
1769  cases (lt_to_not_zero … relevant)
1770qed.
1771
1772lemma ltb_false_to_not_lt: ∀p,q:ℕ.ltb p q = false → p ≮ q.
1773  #p #q #H @leb_false_to_not_le @H
1774qed.
1775
1776lemma ltb_true_to_lt: ∀p,q:ℕ.ltb p q = true → p < q.
1777 #p #q #H @leb_true_to_le @H
1778qed.
1779 
1780lemma plus_equals_zero: ∀x,y:ℕ.x + y = x → y = 0.
1781 #x #y cases y
1782 [ #_ @refl
1783 | -y #y elim x
1784   [ <plus_O_n / by /
1785   | -x #x #Hind #H2 @Hind normalize in H2; @injective_S @H2
1786   ]
1787 ]
1788qed.
Note: See TracBrowser for help on using the repository browser.