source: src/ASM/Util.ma @ 3341

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