source: src/ASM/Util.ma @ 2125

Last change on this file since 2125 was 2125, checked in by boender, 7 years ago
  • some more displacement from Policy to Util
File size: 40.0 KB
RevLine 
[1599]1include "basics/lists/list.ma".
[697]2include "basics/types.ma".
[712]3include "arithmetics/nat.ma".
[1600]4include "basics/russell.ma".
[1062]5
[990]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.
[1059]11
[1159]12notation "⊥" with precedence 90
13  for @{ match ? in False with [ ] }.
[1882]14notation "Ⓧ" with precedence 90
15  for @{ λabs.match abs in False with [ ] }.
[1159]16
[1882]17
[1063]18definition ltb ≝
19  λm, n: nat.
20    leb (S m) n.
21   
22definition geb ≝
23  λm, n: nat.
[1811]24    leb n m.
[1063]25
26definition gtb ≝
27  λm, n: nat.
[1279]28    ltb n m.
[1063]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  ].
[1094]36
[1193]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
[1094]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  ].
[1064]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.
[1063]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
[1064]146definition hd_safe ≝
[1062]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
[1064]153  ] proof.
[1062]154  normalize in nil_absrd;
155  cases(not_le_Sn_O 0)
156  #HYP
157  cases(HYP nil_absrd)
158qed.
159
[1064]160definition tail_safe ≝
[1062]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
[1064]167  ] proof.
[1062]168  normalize in nil_absrd;
169  cases(not_le_Sn_O 0)
170  #HYP
171  cases(HYP nil_absrd)
172qed.
173
[2032]174let rec safe_split
[1075]175  (A: Type[0]) (l: list A) (index: nat) (proof: index ≤ |l|)
[1062]176    on index ≝
[1075]177  match index return λx. x ≤ |l| → (list A) × (list A) with
[1062]178  [ O ⇒ λzero_prf. 〈[], l〉
179  | S index' ⇒ λsucc_prf.
[1075]180    match l return λx. S index' ≤ |x| → (list A) × (list A) with
[1062]181    [ nil ⇒ λnil_absrd. ?
182    | cons hd tl ⇒ λcons_prf.
[2032]183      let 〈l1, l2〉 ≝ safe_split A tl index' ? in
[1062]184        〈hd :: l1, l2〉
185    ] succ_prf
186  ] proof.
187  [1: normalize in nil_absrd;
[1075]188      cases(not_le_Sn_O index')
[1062]189      #HYP
190      cases(HYP nil_absrd)
191  |2: normalize in cons_prf;
192      @le_S_S_to_le
193      assumption
194  ]
195qed.
196
[1060]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)
[1516]222  | normalize in cons_proof;
[1060]223    @le_S_S_to_le
224    assumption
225  ]
226qed.
227
[2055]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
[2111]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.
[2055]262
[2111]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
[1060]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 ?.
[1811]292  normalize /2 by lt_plus_to_minus/
[1060]293qed.
294
[1059]295let rec reduce
[1071]296  (A: Type[0]) (B: Type[0]) (left: list A) (right: list B) on left ≝
[1059]297  match left with
298  [ nil ⇒ 〈〈[ ], [ ]〉, 〈[ ], right〉〉
299  | cons hd tl ⇒
300    match right with
301    [ nil ⇒ 〈〈[ ], left〉, 〈[ ], [ ]〉〉
302    | cons hd' tl' ⇒
[1071]303      let 〈cleft, cright〉 ≝ reduce A B tl tl' in
[1059]304      let 〈commonl, restl〉 ≝ cleft in
305      let 〈commonr, restr〉 ≝ cright in
306        〈〈hd :: commonl, restl〉, 〈hd' :: commonr, restr〉〉
307    ]
308  ].
309
[1062]310(*
[1060]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) |.
[1062]316*)
[1060]317
[1059]318let rec reduce_strong
[1071]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)|  ≝
[1063]321  match left with
322  [ nil ⇒ 〈〈[ ], [ ]〉, 〈[ ], right〉〉
[1059]323  | cons hd tl ⇒
[1063]324    match right with
325    [ nil ⇒ 〈〈[ ], left〉, 〈[ ], [ ]〉〉
326    | cons hd' tl' ⇒
[2005]327      let 〈cleft, cright〉 ≝ pi1 ?? (reduce_strong A B tl tl') in
[1063]328      let 〈commonl, restl〉 ≝ cleft in
329      let 〈commonr, restr〉 ≝ cright in
330        〈〈hd :: commonl, restl〉, 〈hd' :: commonr, restr〉〉
[1059]331    ]
[1063]332  ].
333  [ 1: normalize %
334  | 2: normalize %
[1600]335  | 3: normalize >p3 in p2; >p4 cases (reduce_strong … tl tl1) normalize
336       #X #H #EQ destruct // ]
337qed.
[1059]338   
[1057]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.
[1061]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.
[1057]431 
[782]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.
[1516]436  #A #a #P #H #x #p lapply H lapply P cases p //
[782]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:
[1516]455    normalize in prf2;
[782]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 
[777]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  ]. 
[475]531
[777]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
[1071]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
[777]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
[698]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
[998]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 %
[1516]617  | #hd #tl #IH #pre whd in ⊢ (???%); <(foldl_step … H ??) applyS (IH (pre@[hd])) ]
[998]618qed.
619
[1882]620(* redirecting to library reverse *)
621definition rev ≝ reverse.
[1064]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 %
[1882]650  | #HD #TL normalize #IH
651    >rev_append_def
652    >rev_append_def
653    >rev_append_def
654    >append_nil
655    normalize
656    >IH
[1064]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  [ %
[1882]668  | #HD #TL normalize #IH
669    >rev_append_def
[1064]670    >(append_length A (rev A TL) [HD])
[1882]671    normalize /2 by /
[1064]672  ]
673qed.
[1159]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
[475]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) ≝
[697]737  match ltb n (S p) with
[475]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.
[1598]784    mk_Prod … (m ÷ n) (modulus m n).
[475]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)"
[1908]795 left associative with precedence 55
[475]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
[1811]804 /2 by le_n, le_S/
[475]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
[1811]819     /2 by /
820   | /3 by not_le_to_not_le_S_S/
[475]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
[1811]836 | #n #H lapply (H1 … H) /2 by le_S_S/
[475]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)
[1811]848 /3 by /
[856]849qed.
[985]850
[1928]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
[1964]1120    #absurd @inductive_hypothesis /2 by injective_S/
[1928]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
[985]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
[1602]1314    /3 by trans_eq, orb_true_l/
[985]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
[1599]1325  [ /2 by conj/
[985]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
[1928]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
[985]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
[1882]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
[985]1387lemma eq_false_to_notb: ∀b. b = false → ¬ b.
[1882]1388 *; /2 by eq_true_false, I/
[985]1389qed.
1390
[1882]1391lemma not_b_to_eq_false : ∀b : bool. Not (bool_to_Prop b) → b = false.
1392** #H [elim (H ?) % | %]
1393qed.
1394
1395(* with this you can use prf : ¬b with b : bool with rewriting
1396   >prf rewrites b as false *)
1397coercion not_bool_to_Prop_to_eq : ∀b : bool.∀prf : Not (bool_to_Prop b).b = false
1398 ≝ not_b_to_eq_false on _prf : Not (bool_to_Prop ?) to (? = false).
1399
1400
1401lemma true_or_false_Prop : ∀b : bool.Or (bool_to_Prop b) (¬(bool_to_Prop b)).
1402* [%1 % | %2 % *]
1403qed.
1404
1405lemma eq_true_to_b : ∀b. b = true → b.
1406#b #btrue >btrue %
1407qed.
1408
1409definition if_then_else_safe : ∀A : Type[0].∀b : bool.(b → A) → (¬(bool_to_Prop b) → A) → A ≝
1410  λA,b,f,g.
1411  match b return λx.match x with [true ⇒ bool_to_Prop b | false ⇒ ¬bool_to_Prop b] → A with
1412  [ true ⇒ f
1413  | false ⇒ g
1414  ] ?. elim b % *
1415qed.
1416
1417notation > "'If' b 'then' 'with' ident prf1 'do' f 'else' 'with' ident prf2 'do' g" with precedence 46 for
1418  @{'if_then_else_safe $b (λ${ident prf1}.$f) (λ${ident prf2}.$g)}.
1419notation > "'If' b 'then' 'with' ident prf1 : ty1 'do' f 'else' 'with' ident prf2 : ty2 'do' g" with precedence 46 for
1420  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1421notation > "'If' b 'then' f 'else' 'with' ident prf2 'do' g" with precedence 46 for
1422  @{'if_then_else_safe $b (λ_.$f) (λ${ident prf2}.$g)}.
1423notation > "'If' b 'then' f 'else' 'with' ident prf2 : ty2 'do' g" with precedence 46 for
1424  @{'if_then_else_safe $b (λ_.$f) (λ${ident prf2}:$ty2.$g)}.
1425notation > "'If' b 'then' 'with' ident prf1 'do' f 'else' g" with precedence 46 for
1426  @{'if_then_else_safe $b (λ${ident prf1}.$f) (λ_.$g)}.
1427notation > "'If' b 'then' 'with' ident prf1 : ty1 'do' f 'else' g" with precedence 46 for
1428  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ_.$g)}.
1429
1430notation < "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
1431  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1432notation < "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
1433  @{'if_then_else_safe $b (λ_:$ty1.$f) (λ${ident prf2}:$ty2.$g)}.
1434notation < "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
1435  @{'if_then_else_safe $b (λ${ident prf1}:$ty1.$f) (λ_:$ty2.$g)}.
1436 
1437interpretation "dependent if then else" 'if_then_else_safe b f g = (if_then_else_safe ? b f g).
1438
[1928]1439(* Also extracts an equality proof (useful when not using Russell). *)
1440notation > "hvbox('let' 〈ident x,ident y〉 'as' ident E 'return' ty ≝ t 'in' s)"
1441 with precedence 10
1442for @{ match $t return λx.∀${ident E}: x = $t. $ty with [ mk_Prod ${ident x} ${ident y} ⇒
1443        λ${ident E}.$s ] (refl ? $t) }.
1444
1445notation > "hvbox('deplet' 〈ident x,ident y〉 'as' ident E  ≝ t 'in' s)"
1446 with precedence 10
1447for @{ match $t return λx.∀${ident E}: x = $t. Σz: ?. ? with [ mk_Prod ${ident x} ${ident y} ⇒
1448        λ${ident E}.$s ] (refl ? $t) }.
1449
1450notation > "hvbox('deplet' 〈ident x,ident y,ident z〉 'as' ident E ≝ t 'in' s)"
1451 with precedence 10
1452for @{ match $t return λx.∀${fresh w}:x = $t. Σq: ?. ? with [ mk_Prod ${fresh xy} ${ident z} ⇒
1453       match ${fresh xy} return λx.∀${ident E}:? = $t. Σu: ?. ? with [ mk_Prod ${ident x} ${ident y} ⇒
1454        λ${ident E}.$s ] ] (refl ? $t) }.
1455
1456notation > "hvbox('let' 〈ident x,ident y,ident z〉 'as' ident E 'return' ty ≝ t 'in' s)"
1457 with precedence 10
1458for @{ match $t return λx.∀${fresh w}:x = $t. Σq: ?. ? with [ mk_Prod ${fresh xy} ${ident z} ⇒
1459       match ${fresh xy} return λx.∀${ident E}:? = $t. $ty with [ mk_Prod ${ident x} ${ident y} ⇒
1460        λ${ident E}.$s ] ] (refl ? $t) }.
1461
[985]1462lemma length_append:
1463 ∀A.∀l1,l2:list A.
1464  |l1 @ l2| = |l1| + |l2|.
1465 #A #l1 elim l1
1466  [ //
1467  | #hd #tl #IH #l2 normalize <IH //]
1468qed.
[1934]1469
1470lemma nth_cons:
1471  ∀n,A,h,t,y.
1472  nth (S n) A (h::t) y = nth n A t y.
1473 #n #A #h #t #y /2 by refl/
1474qed.
1475
1476lemma option_destruct_Some: ∀A,a,b. Some A a = Some A b → a=b.
1477 #A #a #b #EQ destruct //
[1937]1478qed.
1479
[2124]1480(*CSC: just a synonim, get rid of it!*)
1481lemma Some_eq:
1482 ∀T:Type[0].∀x,y:T. Some T x = Some T y → x = y ≝ option_destruct_Some.
1483
[1937]1484lemma pi1_eq: ∀A:Type[0].∀P:A->Prop.∀s1:Σa1:A.P a1.∀s2:Σa2:A.P a2.
1485  s1 = s2 → (pi1 ?? s1) = (pi1 ?? s2).
1486 #A #P #s1 #s2 / by /
1487qed.
1488
[1964]1489lemma not_neq_None_to_eq : ∀A.∀a : option A.¬a≠None ? → a = None ?.
1490#A * [2: #a] * // #ABS elim (ABS ?) % #ABS' destruct(ABS')
1491qed.
1492
1493coercion not_neq_None : ∀A.∀a : option A.∀prf : ¬a≠None ?.a = None ? ≝
[2032]1494  not_neq_None_to_eq on _prf : ¬?≠None ? to ? = None ?.
[2124]1495
1496lemma None_Some_elim: ∀P:Prop. ∀A,a. None A = Some A a → P.
1497 #P #A #a #abs destruct
1498qed.
1499
1500discriminator Prod.
1501
1502lemma pair_replace:
1503 ∀A,B,T:Type[0].∀P:T → Prop. ∀t. ∀a,b.∀c,c': A × B. c'=c → c ≃ 〈a,b〉 →
1504  P (t a b) → P (let 〈a',b'〉 ≝ c' in t a' b').
1505 #A #B #T #P #t #a #b * #x #y * #x' #y' #H1 #H2 destruct //
1506qed.
1507
1508lemma jmpair_as_replace:
1509 ∀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.
1510  ∀EQ:c ≃ 〈a,b〉.
1511  P (t a b ?) → P ((let 〈a',b'〉 (*as H*) ≝ c' in λH. t a' b' H) (refl_jmeq ? c')).
1512  [2:
1513    >EQc @EQ
1514  |1:
1515    #A #B #T #P #a #b
1516    #c #c' #t #EQc >EQc in t; -c' normalize #f #EQ
1517    letin eta ≝ (? : ∀ab:A × B.∀P:A × B → Type[0]. P ab → P 〈\fst ab,\snd ab〉) [2: * // ]
1518    change with (eta 〈a,b〉 (λab.c ≃ ab) EQ) in match EQ;
1519    @(jmeq_elim ?? (λab.λH.P (f (\fst ab) (\snd ab) ?) → ?) ?? EQ) normalize -eta
1520    -EQ cases c in f; normalize //
1521  ]
1522qed.
1523
1524lemma if_then_else_replace:
1525  ∀T: Type[0].
1526  ∀P: T → Prop.
1527  ∀t1, t2: T.
1528  ∀c, c', c'': bool.
1529    c' = c → c ≃ c'' → P (if c'' then t1 else t2) → P (if c' then t1 else t2).
1530  #T #P #t1 #t2 #c #c' #c'' #c_refl #c_refl' destruct #assm
1531  assumption
1532qed.
1533
1534lemma refl_to_jmrefl:
1535  ∀a: Type[0].
1536  ∀l, r: a.
1537    l = r → l ≃ r.
1538  #a #l #r #refl destruct %
1539qed.
1540
1541lemma prod_eq_left:
1542  ∀A: Type[0].
1543  ∀p, q, r: A.
1544    p = q → 〈p, r〉 = 〈q, r〉.
1545  #A #p #q #r #hyp
1546  destruct %
1547qed.
1548
1549lemma prod_eq_right:
1550  ∀A: Type[0].
1551  ∀p, q, r: A.
1552    p = q → 〈r, p〉 = 〈r, q〉.
1553  #A #p #q #r #hyp
1554  destruct %
1555qed.
1556
1557lemma destruct_bug_fix_1:
1558  ∀n: nat.
1559    S n = 0 → False.
1560  #n #absurd destruct(absurd)
1561qed.
1562
1563lemma destruct_bug_fix_2:
1564  ∀m, n: nat.
1565    S m = S n → m = n.
1566  #m #n #refl destruct %
1567qed.
1568
1569lemma eq_rect_Type1_r:
1570  ∀A: Type[1].
1571  ∀a: A.
1572  ∀P: ∀x:A. eq ? x a → Type[1]. P a (refl A a) → ∀x: A.∀p:eq ? x a. P x p.
1573  #A #a #P #H #x #p
1574  generalize in match H;
1575  generalize in match P;
1576  cases p //
1577qed.
1578
1579lemma Some_Some_elim:
1580 ∀T:Type[0].∀x,y:T.∀P:Type[2]. (x=y → P) → Some T x = Some T y → P.
1581 #T #x #y #P #H #K @H @option_destruct_Some //
1582qed.
1583
1584lemma pair_destruct_right:
1585  ∀A: Type[0].
1586  ∀B: Type[0].
1587  ∀a, c: A.
1588  ∀b, d: B.
1589    〈a, b〉 = 〈c, d〉 → b = d.
1590  #A #B #a #b #c #d //
1591qed.
1592
1593lemma pose: ∀A:Type[0].∀B:A → Type[0].∀a:A. (∀a':A. a'=a → B a') → B a.
1594  /2/
1595qed.
1596
1597definition eq_sum:
1598    ∀A, B. (A → A → bool) → (B → B → bool) → (A ⊎ B) → (A ⊎ B) → bool ≝
1599  λlt, rt, leq, req, left, right.
1600    match left with
1601    [ inl l ⇒
1602      match right with
1603      [ inl l' ⇒ leq l l'
1604      | _ ⇒ false
1605      ]
1606    | inr r ⇒
1607      match right with
1608      [ inr r' ⇒ req r r'
1609      | _ ⇒ false
1610      ]
1611    ].
1612
1613lemma eq_sum_refl:
1614  ∀A, B: Type[0].
1615  ∀leq, req.
1616  ∀s.
1617  ∀leq_refl: (∀t. leq t t = true).
1618  ∀req_refl: (∀u. req u u = true).
1619    eq_sum A B leq req s s = true.
1620  #A #B #leq #req #s #leq_refl #req_refl
1621  cases s assumption
1622qed.
1623
1624definition eq_prod: ∀A, B. (A → A → bool) → (B → B → bool) → (A × B) → (A × B) → bool ≝
1625  λlt, rt, leq, req, left, right.
1626    let 〈l, r〉 ≝ left in
1627    let 〈l', r'〉 ≝ right in
1628      leq l l' ∧ req r r'.
1629
1630lemma eq_prod_refl:
1631  ∀A, B: Type[0].
1632  ∀leq, req.
1633  ∀s.
1634  ∀leq_refl: (∀t. leq t t = true).
1635  ∀req_refl: (∀u. req u u = true).
1636    eq_prod A B leq req s s = true.
1637  #A #B #leq #req #s #leq_refl #req_refl
1638  cases s
1639  whd in ⊢ (? → ? → ??%?);
1640  #l #r
1641  >leq_refl @req_refl
1642qed.
[2123]1643 
1644lemma geb_to_leb: ∀a,b:ℕ.geb a b = leb b a.
1645  #a #b / by refl/
1646qed.
1647
1648lemma nth_last: ∀A,a,l.
1649  nth (|l|) A l a = a.
1650 #A #a #l elim l
1651 [ / by /
1652 | #h #t #Hind whd in match (nth ????); whd in match (tail ??); @Hind
1653 ]
1654qed.
1655
1656
1657lemma minus_zero_to_le: ∀n,m:ℕ.n - m = 0 → n ≤ m.
1658 #n
1659 elim n
1660 [ #m #_ @le_O_n
1661 | #n' #Hind #m cases m
1662   [ #H -n whd in match (minus ??) in H; >H @le_n
1663   | #m' -m #H whd in match (minus ??) in H; @le_S_S @Hind @H
1664   ]
1665 ]
1666qed.
1667
1668lemma plus_zero_zero: ∀n,m:ℕ.n + m = 0 → m = 0.
1669 #n #m #Hn @sym_eq @le_n_O_to_eq <Hn >commutative_plus @le_plus_n_r
1670qed.
1671
1672(* this can probably be done more simply somewhere *)
1673lemma not_true_is_false:
1674  ∀b:bool.b ≠ true → b = false.
1675 #b cases b
1676 [ #H @⊥ @(absurd ?? H) @refl
1677 | #H @refl
1678 ]
[2124]1679qed.
[2125]1680
1681(* this is in the stdlib, but commented out, why? *)
1682theorem plus_Sn_m1: ∀n,m:nat. S m + n = m + S n.
1683  #n (elim n) normalize /2 by S_pred/ qed.
1684 
1685(* these lemmas seem superfluous, but not sure how to replace them *)
1686lemma double_plus_equal: ∀a,b:ℕ.a + a = b + b → a = b.
1687 #a elim a
1688 [ normalize #b //
1689 | -a #a #Hind #b cases b [ /2 by le_n_O_to_eq/ | -b #b normalize
1690   <plus_n_Sm <plus_n_Sm #H
1691   >(Hind b (injective_S ?? (injective_S ?? H))) // ]
1692 ]
1693qed.
1694
1695lemma sth_not_s: ∀x.x ≠ S x.
1696 #x cases x
1697 [ // | #y // ]
1698qed.
1699 
1700lemma le_to_eq_plus: ∀n,z.
1701  n ≤ z → ∃k.z = n + k.
1702 #n #z elim z
1703 [ #H cases (le_to_or_lt_eq … H)
1704   [ #H2 @⊥ @(absurd … H2) @not_le_Sn_O
1705   | #H2 @(ex_intro … 0) >H2 //
1706   ]
1707 | #z' #Hind #H cases (le_to_or_lt_eq … H)
1708   [ #H' elim (Hind (le_S_S_to_le … H')) #k' #H2 @(ex_intro … (S k'))
1709     >H2 >plus_n_Sm //
1710   | #H' @(ex_intro … 0) >H' //
1711   ]
1712 ]
1713qed.
1714
1715lemma nth_safe_nth:
1716  ∀A:Type[0].∀l:list A.∀i.∀proof:i < |l|.∀x.nth_safe A i l proof = nth i A l x.
1717#A #l elim l
1718[ #i #prf @⊥ @(absurd ? prf) @le_to_not_lt @le_O_n
1719| -l #h #t #Hind #i elim i
1720  [ #prf #x normalize @refl
1721  | -i #i #Hind2 #prf #x whd in match (nth ????); whd in match (tail ??);
1722    whd in match (nth_safe ????); @Hind
1723  ]
1724]
1725qed.
1726
Note: See TracBrowser for help on using the repository browser.