]> matita.cs.unibo.it Git - helm.git/blob - weblib/Cerco/ASM/Utils.ma
commit by user andrea
[helm.git] / weblib / Cerco / ASM / Utils.ma
1 include "basics/list.ma".
2 include "basics/types.ma".
3 include "arithmetics/nat.ma".
4
5 include "utilities/pair.ma".
6 include "ASM/JMCoercions.ma".
7
8 (* let's implement a daemon not used by automation *)
9 inductive DAEMONXXX: Type[0] ≝ K1DAEMONXXX: DAEMONXXX | K2DAEMONXXX: DAEMONXXX.
10 axiom IMPOSSIBLE: K1DAEMONXXX = K2DAEMONXXX.
11 example daemon: False. generalize in match IMPOSSIBLE; #IMPOSSIBLE destruct(IMPOSSIBLE) qed.
12 example not_implemented: False. cases daemon qed.
13
14 notation "⊥" with precedence 90
15   for @{ match ? in False with [ ] }.
16
17 definition ltb ≝
18   λm, n: nat.
19     leb (S m) n.
20     
21 definition geb ≝
22   λm, n: nat.
23     ltb n m.
24
25 definition gtb ≝
26   λm, n: nat.
27     ltb n m.
28
29 (* dpm: unless I'm being stupid, this isn't defined in the stdlib? *)
30 let rec eq_nat (n: nat) (m: nat) on n: bool ≝
31   match n with
32   [ O ⇒ match m with [ O ⇒ true | _ ⇒ false ]
33   | S n' ⇒ match m with [ S m' ⇒ eq_nat n' m' | _ ⇒ false ]
34   ].
35
36 let rec forall
37   (A: Type[0]) (f: A → bool) (l: list A)
38     on l ≝
39   match l with
40   [ nil        ⇒ true
41   | cons hd tl ⇒ f hd ∧ forall A f tl
42   ].
43
44 let rec prefix
45   (A: Type[0]) (k: nat) (l: list A)
46     on l ≝
47   match l with
48   [ nil ⇒ [ ]
49   | cons hd tl ⇒
50     match k with
51     [ O ⇒ [ ]
52     | S k' ⇒ hd :: prefix A k' tl
53     ]
54   ].
55   
56 let rec fold_left2
57   (A: Type[0]) (B: Type[0]) (C: Type[0]) (f: A → B → C → A) (accu: A)
58   (left: list B) (right: list C) (proof: |left| = |right|)
59     on left: A ≝
60   match left return λx. |x| = |right| → A with
61   [ nil ⇒ λnil_prf.
62     match right return λx. |[ ]| = |x| → A with
63     [ nil ⇒ λnil_nil_prf. accu
64     | cons hd tl ⇒ λcons_nil_absrd. ?
65     ] nil_prf
66   | cons hd tl ⇒ λcons_prf.
67     match right return λx. |hd::tl| = |x| → A with
68     [ nil ⇒ λcons_nil_absrd. ?
69     | cons hd' tl' ⇒ λcons_cons_prf.
70         fold_left2 …  f (f accu hd hd') tl tl' ?
71     ] cons_prf
72   ] proof.
73   [ 1: normalize in cons_nil_absrd;
74        destruct(cons_nil_absrd)
75   | 2: normalize in cons_nil_absrd;
76        destruct(cons_nil_absrd)
77   | 3: normalize in cons_cons_prf;
78        @injective_S
79        assumption
80   ]
81 qed.
82
83 let rec remove_n_first_internal
84   (i: nat) (A: Type[0]) (l: list A) (n: nat)
85     on l ≝
86   match l with
87   [ nil ⇒ [ ]
88   | cons hd tl ⇒
89     match eq_nat i n with
90     [ true ⇒ l
91     | _ ⇒ remove_n_first_internal (S i) A tl n
92     ]
93   ].
94
95 definition remove_n_first ≝
96   λA: Type[0].
97   λn: nat.
98   λl: list A.
99     remove_n_first_internal 0 A l n.
100     
101 let rec foldi_from_until_internal
102   (A: Type[0]) (i: nat) (res: ?) (rem: list A) (m: nat) (f: nat → list A → A → list A)
103     on rem ≝
104   match rem with
105   [ nil ⇒ res
106   | cons e tl ⇒
107     match geb i m with
108     [ true ⇒ res
109     | _ ⇒ foldi_from_until_internal A (S i) (f i res e) tl m f
110     ]
111   ].
112
113 definition foldi_from_until ≝
114   λA: Type[0].
115   λn: nat.
116   λm: nat.
117   λf: ?.
118   λa: ?.
119   λl: ?.
120     foldi_from_until_internal A 0 a (remove_n_first A n l) m f.
121
122 definition foldi_from ≝
123   λA: Type[0].
124   λn.
125   λf.
126   λa.
127   λl.
128     foldi_from_until A n (|l|) f a l.
129
130 definition foldi_until ≝
131   λA: Type[0].
132   λm.
133   λf.
134   λa.
135   λl.
136     foldi_from_until A 0 m f a l.
137
138 definition foldi ≝
139   λA: Type[0].
140   λf.
141   λa.
142   λl.
143     foldi_from_until A 0 (|l|) f a l.
144
145 definition hd_safe ≝
146   λA: Type[0].
147   λl: list A.
148   λproof: 0 < |l|.
149   match l return λx. 0 < |x| → A with
150   [ nil ⇒ λnil_absrd. ?
151   | cons hd tl ⇒ λcons_prf. hd
152   ] proof.
153   normalize in nil_absrd;
154   cases(not_le_Sn_O 0)
155   #HYP
156   cases(HYP nil_absrd)
157 qed.
158
159 definition tail_safe ≝
160   λA: Type[0].
161   λl: list A.
162   λproof: 0 < |l|.
163   match l return λx. 0 < |x| → list A with
164   [ nil ⇒ λnil_absrd. ?
165   | cons hd tl ⇒ λcons_prf. tl
166   ] proof.
167   normalize in nil_absrd;
168   cases(not_le_Sn_O 0)
169   #HYP
170   cases(HYP nil_absrd)
171 qed.
172
173 let rec split
174   (A: Type[0]) (l: list A) (index: nat) (proof: index ≤ |l|)
175     on index ≝
176   match index return λx. x ≤ |l| → (list A) × (list A) with
177   [ O ⇒ λzero_prf. 〈[], l〉
178   | S index' ⇒ λsucc_prf.
179     match l return λx. S index' ≤ |x| → (list A) × (list A) with
180     [ nil ⇒ λnil_absrd. ?
181     | cons hd tl ⇒ λcons_prf.
182       let 〈l1, l2〉 ≝ split A tl index' ? in
183         〈hd :: l1, l2〉
184     ] succ_prf
185   ] proof.
186   [1: normalize in nil_absrd;
187       cases(not_le_Sn_O index')
188       #HYP
189       cases(HYP nil_absrd)
190   |2: normalize in cons_prf;
191       @le_S_S_to_le
192       assumption
193   ]
194 qed.
195
196 let rec nth_safe
197   (elt_type: Type[0]) (index: nat) (the_list: list elt_type)
198   (proof: index < | the_list |)
199     on index ≝
200   match index return λs. s < | the_list | → elt_type with
201   [ O ⇒
202     match the_list return λt. 0 < | t | → elt_type with
203     [ nil        ⇒ λnil_absurd. ?
204     | cons hd tl ⇒ λcons_proof. hd
205     ]
206   | S index' ⇒
207     match the_list return λt. S index' < | t | → elt_type with
208     [ nil ⇒ λnil_absurd. ?
209     | cons hd tl ⇒
210       λcons_proof. nth_safe elt_type index' tl ?
211     ]
212   ] proof.
213   [ normalize in nil_absurd;
214     cases (not_le_Sn_O 0)
215     #ABSURD
216     elim (ABSURD nil_absurd)
217   | normalize in nil_absurd;
218     cases (not_le_Sn_O (S index'))
219     #ABSURD
220     elim (ABSURD nil_absurd)
221   | normalize in cons_proof
222     @le_S_S_to_le
223     assumption
224   ]
225 qed.
226
227 definition last_safe ≝
228   λelt_type: Type[0].
229   λthe_list: list elt_type.
230   λproof   : 0 < | the_list |.
231     nth_safe elt_type (|the_list| - 1) the_list ?.
232   normalize /2/
233 qed.
234
235 let rec reduce 
236   (A: Type[0]) (B: Type[0]) (left: list A) (right: list B) on left ≝
237   match left with
238   [ nil ⇒ 〈〈[ ], [ ]〉, 〈[ ], right〉〉
239   | cons hd tl ⇒
240     match right with
241     [ nil ⇒ 〈〈[ ], left〉, 〈[ ], [ ]〉〉
242     | cons hd' tl' ⇒
243       let 〈cleft, cright〉 ≝ reduce A B tl tl' in
244       let 〈commonl, restl〉 ≝ cleft in
245       let 〈commonr, restr〉 ≝ cright in
246         〈〈hd :: commonl, restl〉, 〈hd' :: commonr, restr〉〉
247     ]
248   ].
249
250 (*
251 axiom reduce_strong:
252   ∀A: Type[0].
253   ∀left: list A.
254   ∀right: list A.
255     Σret: ((list A) × (list A)) × ((list A) × (list A)). | \fst (\fst ret) | = | \fst (\snd ret) |.
256 *)
257
258 let rec reduce_strong
259   (A: Type[0]) (B: Type[0]) (left: list A) (right: list B)
260     on left : Σret: ((list A) × (list A)) × ((list B) × (list B)). |\fst (\fst ret)| = |\fst (\snd ret)|  ≝
261   match left with
262   [ nil ⇒ 〈〈[ ], [ ]〉, 〈[ ], right〉〉
263   | cons hd tl ⇒
264     match right with
265     [ nil ⇒ 〈〈[ ], left〉, 〈[ ], [ ]〉〉
266     | cons hd' tl' ⇒
267       let 〈cleft, cright〉 ≝ reduce_strong A B tl tl' in
268       let 〈commonl, restl〉 ≝ cleft in
269       let 〈commonr, restr〉 ≝ cright in
270         〈〈hd :: commonl, restl〉, 〈hd' :: commonr, restr〉〉
271     ]
272   ].
273   [ 1: normalize %
274   | 2: normalize %
275   | 3: normalize
276        generalize in match (sig2 … (reduce_strong A B tl tl1));
277        >p2 >p3 >p4 normalize in ⊢ (% → ?)
278        #HYP //
279   ]
280 qed. 
281     
282 let rec map2_opt
283   (A: Type[0]) (B: Type[0]) (C: Type[0]) (f: A → B → C)
284   (left: list A) (right: list B) on left ≝
285   match left with
286   [ nil ⇒
287     match right with
288     [ nil ⇒ Some ? (nil C)
289     | _ ⇒ None ?
290     ]
291   | cons hd tl ⇒
292     match right with
293     [ nil ⇒ None ?
294     | cons hd' tl' ⇒
295       match map2_opt A B C f tl tl' with
296       [ None ⇒ None ?
297       | Some tail ⇒ Some ? (f hd hd' :: tail)
298       ]
299     ]
300   ].
301
302 let rec map2
303   (A: Type[0]) (B: Type[0]) (C: Type[0]) (f: A → B → C)
304   (left: list A) (right: list B) (proof: | left | = | right |) on left ≝
305   match left return λx. | x | = | right | → list C with
306   [ nil ⇒
307     match right return λy. | [] | = | y | → list C with
308     [ nil ⇒ λnil_prf. nil C
309     | _ ⇒ λcons_absrd. ?
310     ]
311   | cons hd tl ⇒
312     match right return λy. | hd::tl | = | y | → list C with
313     [ nil ⇒ λnil_absrd. ?
314     | cons hd' tl' ⇒ λcons_prf. (f hd hd') :: map2 A B C f tl tl' ?
315     ]
316   ] proof.
317   [1: normalize in cons_absrd;
318       destruct(cons_absrd)
319   |2: normalize in nil_absrd;
320       destruct(nil_absrd)
321   |3: normalize in cons_prf;
322       destruct(cons_prf)
323       assumption
324   ]
325 qed.
326
327 let rec map3
328   (A: Type[0]) (B: Type[0]) (C: Type[0]) (D: Type[0]) (f: A → B → C → D)
329   (left: list A) (centre: list B) (right: list C)
330   (prflc: |left| = |centre|) (prfcr: |centre| = |right|) on left ≝
331   match left return λx. |x| = |centre| → list D with
332   [ nil ⇒ λnil_prf.
333     match centre return λx. |x| = |right| → list D with
334     [ nil ⇒ λnil_nil_prf.
335       match right return λx. |nil ?| = |x| → list D with
336       [ nil        ⇒ λnil_nil_nil_prf. nil D
337       | cons hd tl ⇒ λcons_nil_nil_absrd. ?
338       ] nil_nil_prf
339     | cons hd tl ⇒ λnil_cons_absrd. ?
340     ] prfcr
341   | cons hd tl ⇒ λcons_prf.
342     match centre return λx. |x| = |right| → list D with
343     [ nil ⇒ λcons_nil_absrd. ?
344     | cons hd' tl' ⇒ λcons_cons_prf.
345       match right return λx. |right| = |x| → |cons ? hd' tl'| = |x| → list D with
346       [ nil ⇒ λrefl_prf. λcons_cons_nil_absrd. ?
347       | cons hd'' tl'' ⇒ λrefl_prf. λcons_cons_cons_prf.
348         (f hd hd' hd'') :: (map3 A B C D f tl tl' tl'' ? ?)
349       ] (refl ? (|right|)) cons_cons_prf
350     ] prfcr
351   ] prflc.
352   [ 1: normalize in cons_nil_nil_absrd;
353        destruct(cons_nil_nil_absrd)
354   | 2: generalize in match nil_cons_absrd;
355        \ 5prfcr\ 6\ 5nil_prf #hyp="" normalize="" hyp;="" destruct(hyp)="" |="" 3:="" generalize="" in="" match="" cons_nil_absrd;=""\ 6\ 5prfcr\ 6\ 5cons_prf #hyp="" hyp;="" destruct(hyp)="" 4:="" cons_cons_nil_absrd;="" destruct(cons_cons_nil_absrd)="" 5:="" normalize="" destruct(cons_cons_cons_prf)="" assumption="" |="" 6:="" generalize="" in="" match="" cons_cons_cons_prf;=""\ 6\ 5refl_prf\ 6\ 5prfcr\ 6\ 5cons_prf #hyp="" normalize="" hyp;="" destruct(hyp)="" @sym_eq="" assumption="" ]="" lemma="" eq_rect_type0_r="" :="" ∀a:="" ∀a:a.="" ∀p:="" ∀x:a.="" eq="" type[0].="" (refl="" a="" →="" ∀x:="" a.∀p:eq="" ?="" a.="" x="" p.="" #a="" #h="" #x="" #p="" h="" generalize="" in="" match="" cases="" p="" qed.="" let="" rec="" safe_nth="" (a:="" type[0])="" (n:="" nat)="" (l:="" list="" a)="" (p:="" n=""\ 6< length A l) on n: A ≝
356   match n return λo. o < length A l → A with
357   [ O ⇒
358     match l return λm. 0 < length A m → A with
359     [ nil ⇒ λabsd1. ?
360     | cons hd tl ⇒ λprf1. hd
361     ]
362   | S n' ⇒
363     match l return λm. S n' < length A m → A with
364     [ nil ⇒ λabsd2. ?
365     | cons hd tl ⇒ λprf2. safe_nth A n' tl ?
366     ]
367   ] ?.
368   [ 1:
369     @ p
370   | 4:
371     normalize in prf2
372     normalize
373     @ le_S_S_to_le
374     assumption
375   | 2:
376     normalize in absd1;
377     cases (not_le_Sn_O O)
378     # H
379     elim (H absd1)
380   | 3:
381     normalize in absd2;
382     cases (not_le_Sn_O (S n'))
383     # H
384     elim (H absd2)
385   ]
386 qed.
387   
388 let rec nub_by_internal (A: Type[0]) (f: A → A → bool) (l: list A) (n: nat) on n ≝
389   match n with
390   [ O ⇒
391     match l with
392     [ nil ⇒ [ ]
393     | cons hd tl ⇒ l
394     ]
395   | S n ⇒
396     match l with
397     [ nil ⇒ [ ]
398     | cons hd tl ⇒
399       hd :: nub_by_internal A f (filter ? (λy. notb (f y hd)) tl) n
400     ]
401   ].
402   
403 definition nub_by ≝
404   λA: Type[0].
405   λf: A → A → bool.
406   λl: list A.
407     nub_by_internal A f l (length ? l).
408   
409 let rec member (A: Type[0]) (eq: A → A → bool) (a: A) (l: list A) on l ≝
410   match l with
411   [ nil ⇒ false
412   | cons hd tl ⇒ orb (eq a hd) (member A eq a tl)
413   ].
414   
415 let rec take (A: Type[0]) (n: nat) (l: list A) on n: list A ≝
416   match n with
417   [ O ⇒ [ ]
418   | S n ⇒
419     match l with
420     [ nil ⇒ [ ]
421     | cons hd tl ⇒ hd :: take A n tl
422     ]
423   ].
424   
425 let rec drop (A: Type[0]) (n: nat) (l: list A) on n ≝
426   match n with
427   [ O ⇒ l
428   | S n ⇒
429     match l with
430     [ nil ⇒ [ ]
431     | cons hd tl ⇒ drop A n tl
432     ]
433   ].
434   
435 definition list_split ≝
436   λA: Type[0].
437   λn: nat.
438   λl: list A.
439     〈take A n l, drop A n l〉.
440   
441 let rec mapi_internal (A: Type[0]) (B: Type[0]) (n: nat) (f: nat → A → B)
442                       (l: list A) on l: list B ≝
443   match l with
444   [ nil ⇒ nil ?
445   | cons hd tl ⇒ (f n hd) :: (mapi_internal A B (n + 1) f tl)
446   ].  
447
448 definition mapi ≝
449   λA, B: Type[0].
450   λf: nat → A → B.
451   λl: list A.
452     mapi_internal A B 0 f l.
453
454 let rec zip_pottier
455   (A: Type[0]) (B: Type[0]) (left: list A) (right: list B)
456     on left ≝
457   match left with
458   [ nil ⇒ [ ]
459   | cons hd tl ⇒
460     match right with
461     [ nil ⇒ [ ]
462     | cons hd' tl' ⇒ 〈hd, hd'〉 :: zip_pottier A B tl tl'
463     ]
464   ].
465
466 let rec zip_safe
467   (A: Type[0]) (B: Type[0]) (left: list A) (right: list B) (prf: |left| = |right|)
468     on left ≝
469   match left return λx. |x| = |right| → list (A × B) with
470   [ nil ⇒ λnil_prf.
471     match right return λx. |[ ]| = |x| → list (A × B) with
472     [ nil ⇒ λnil_nil_prf. [ ]
473     | cons hd tl ⇒ λnil_cons_absrd. ?
474     ] nil_prf
475   | cons hd tl ⇒ λcons_prf.
476     match right return λx. |hd::tl| = |x| → list (A × B) with
477     [ nil ⇒ λcons_nil_absrd. ?
478     | cons hd' tl' ⇒ λcons_cons_prf. 〈hd, hd'〉 :: zip_safe A B tl tl' ?
479     ] cons_prf
480   ] prf.
481   [ 1: normalize in nil_cons_absrd;
482        destruct(nil_cons_absrd)
483   | 2: normalize in cons_nil_absrd;
484        destruct(cons_nil_absrd)
485   | 3: normalize in cons_cons_prf;
486        @injective_S
487        assumption
488   ]
489 qed.
490
491 let rec zip (A: Type[0]) (B: Type[0]) (l: list A) (r: list B) on l: option (list (A × B)) ≝
492   match l with
493   [ nil ⇒ Some ? (nil (A × B))
494   | cons hd tl ⇒
495     match r with
496     [ nil ⇒ None ?
497     | cons hd' tl' ⇒
498       match zip ? ? tl tl' with
499       [ None ⇒ None ?
500       | Some tail ⇒ Some ? (〈hd, hd'〉 :: tail)
501       ]
502     ]
503   ].
504
505 let rec foldl (A: Type[0]) (B: Type[0]) (f: A → B → A) (a: A) (l: list B) on l ≝
506   match l with
507   [ nil ⇒ a
508   | cons hd tl ⇒ foldl A B f (f a hd) tl
509   ].
510
511 lemma foldl_step:
512  ∀A:Type[0].
513   ∀B: Type[0].
514    ∀H: A → B → A.
515     ∀acc: A.
516      ∀pre: list B.
517       ∀hd:B.
518        foldl A B H acc (pre@[hd]) = (H (foldl A B H acc pre) hd).
519  #A #B #H #acc #pre generalize in match acc; -acc; elim pre
520   [ normalize; //
521   | #hd #tl #IH #acc #X normalize; @IH ]
522 qed.
523
524 lemma foldl_append:
525  ∀A:Type[0].
526   ∀B: Type[0].
527    ∀H: A → B → A.
528     ∀acc: A.
529      ∀suff,pre: list B.
530       foldl A B H acc (pre@suff) = (foldl A B H (foldl A B H acc pre) suff).
531  #A #B #H #acc #suff elim suff
532   [ #pre >append_nil %
533   | #hd #tl #IH #pre whd in ⊢ (???%) <(foldl_step … H ??) applyS (IH (pre@[hd])) ] 
534 qed.
535
536 definition flatten ≝
537   λA: Type[0].
538   λl: list (list A).
539     foldr ? ? (append ?) [ ] l.
540
541 let rec rev (A: Type[0]) (l: list A) on l ≝ 
542   match l with
543   [ nil ⇒ nil A
544   | cons hd tl ⇒ (rev A tl) @ [ hd ]
545   ].
546
547 lemma append_length:
548   ∀A: Type[0].
549   ∀l, r: list A.
550     |(l @ r)| = |l| + |r|.
551   #A #L #R
552   elim L
553   [ %
554   | #HD #TL #IH
555     normalize >IH %
556   ]
557 qed.
558
559 lemma append_nil:
560   ∀A: Type[0].
561   ∀l: list A.
562     l @ [ ] = l.
563   #A #L
564   elim L //
565 qed.
566
567 lemma rev_append:
568   ∀A: Type[0].
569   ∀l, r: list A.
570     rev A (l @ r) = rev A r @ rev A l.
571   #A #L #R
572   elim L
573   [ normalize >append_nil %
574   | #HD #TL #IH
575     normalize >IH
576     @associative_append
577   ]
578 qed.
579
580 lemma rev_length:
581   ∀A: Type[0].
582   ∀l: list A.
583     |rev A l| = |l|.
584   #A #L
585   elim L
586   [ %
587   | #HD #TL #IH
588     normalize
589     >(append_length A (rev A TL) [HD])
590     normalize /2/
591   ]
592 qed.
593
594 lemma nth_append_first:
595  ∀A:Type[0].
596  ∀n:nat.∀l1,l2:list A.∀d:A.
597    n < |l1| → nth n A (l1@l2) d = nth n A l1 d.
598  #A #n #l1 #l2 #d
599  generalize in match n; -n; elim l1
600  [ normalize #k #Hk @⊥ @(absurd … Hk) @not_le_Sn_O
601  | #h #t #Hind #k normalize
602    cases k -k 
603    [ #Hk normalize @refl
604    | #k #Hk normalize @(Hind k) @le_S_S_to_le @Hk
605    ]  
606  ]
607 qed.
608
609 lemma nth_append_second: 
610  ∀A: Type[0].∀n.∀l1,l2:list A.∀d.n ≥ length A l1 ->
611   nth n A (l1@l2) d = nth (n - length A l1) A l2 d.
612  #A #n #l1 #l2 #d
613  generalize in match n; -n; elim l1
614  [ normalize #k #Hk <(minus_n_O) @refl
615  | #h #t #Hind #k normalize 
616    cases k -k;
617    [ #Hk @⊥ @(absurd (S (|t|) ≤ 0)) [ @Hk | @not_le_Sn_O ]
618    | #k #Hk normalize @(Hind k) @le_S_S_to_le @Hk
619    ] 
620  ]
621 qed.
622
623     
624 notation > "'if' term 19 e 'then' term 19 t 'else' term 48 f" non associative with precedence 19
625  for @{ match $e in bool with [ true ⇒ $t | false ⇒ $f]  }.
626 notation < "hvbox('if' \nbsp term 19 e \nbsp break 'then' \nbsp term 19 t \nbsp break 'else' \nbsp term 48 f \nbsp)" non associative with precedence 19
627  for @{ match $e with [ true ⇒ $t | false ⇒ $f]  }.
628
629 let rec fold_left_i_aux (A: Type[0]) (B: Type[0])
630                         (f: nat → A → B → A) (x: A) (i: nat) (l: list B) on l ≝
631   match l with
632     [ nil ⇒ x
633     | cons hd tl ⇒ fold_left_i_aux A B f (f i x hd) (S i) tl
634     ].
635
636 definition fold_left_i ≝ λA,B,f,x. fold_left_i_aux A B f x O.
637
638 notation "hvbox(t⌈o ↦ h⌉)"
639   with precedence 45
640   for @{ match (? : $o=$h) with [ refl ⇒ $t ] }.
641
642 definition function_apply ≝
643   λA, B: Type[0].
644   λf: A → B.
645   λa: A.
646     f a.
647     
648 notation "f break $ x"
649   left associative with precedence 99
650   for @{ 'function_apply $f $x }.
651   
652 interpretation "Function application" 'function_apply f x = (function_apply ? ? f x).
653
654 let rec iterate (A: Type[0]) (f: A → A) (a: A) (n: nat) on n ≝
655   match n with
656     [ O ⇒ a
657     | S o ⇒ f (iterate A f a o)
658     ].
659
660 (* Yeah, I probably ought to do something more general... *)
661 notation "hvbox(\langle term 19 a, break term 19 b, break term 19 c\rangle)" 
662 with precedence 90 for @{ 'triple $a $b $c}.
663 interpretation "Triple construction" 'triple x y z = (pair ? ? (pair ? ? x y) z).
664
665 notation "hvbox(\langle term 19 a, break term 19 b, break term 19 c, break term 19 d\rangle)"
666 with precedence 90 for @{ 'quadruple $a $b $c $d}.
667 interpretation "Quadruple construction" 'quadruple w x y z = (pair ? ? (pair ? ? w x) (pair ? ? y z)).
668
669 notation > "hvbox('let' 〈ident w,ident x,ident y,ident z〉 ≝ t 'in' s)"
670  with precedence 10
671 for @{ match $t with [ pair ${fresh wx} ${fresh yz} ⇒ match ${fresh wx} with [ pair ${ident w} ${ident x} ⇒ match ${fresh yz} with [ pair ${ident y} ${ident z} ⇒ $s ] ] ] }.
672
673 notation > "hvbox('let' 〈ident x,ident y,ident z〉 ≝ t 'in' s)"
674  with precedence 10
675 for @{ match $t with [ pair ${fresh xy} ${ident z} ⇒ match ${fresh xy} with [ pair ${ident x} ${ident y} ⇒ $s ] ] }.
676
677 notation < "hvbox('let' \nbsp hvbox(〈ident x,ident y〉\nbsp ≝ break t \nbsp 'in' \nbsp) break s)"
678  with precedence 10
679 for @{ match $t with [ pair (${ident x}:$ignore) (${ident y}:$ignora) ⇒ $s ] }.
680
681 axiom pair_elim':
682   ∀A,B,C: Type[0].
683   ∀T: A → B → C.
684   ∀p.
685   ∀P: A×B → C → Prop.
686     (∀lft, rgt. p = 〈lft,rgt〉 → P 〈lft,rgt〉 (T lft rgt)) →
687       P p (let 〈lft, rgt〉 ≝ p in T lft rgt).
688
689 axiom pair_elim'':
690   ∀A,B,C,C': Type[0].
691   ∀T: A → B → C.
692   ∀T': A → B → C'.
693   ∀p.
694   ∀P: A×B → C → C' → Prop.
695     (∀lft, rgt. p = 〈lft,rgt〉 → P 〈lft,rgt〉 (T lft rgt) (T' lft rgt)) →
696       P p (let 〈lft, rgt〉 ≝ p in T lft rgt) (let 〈lft, rgt〉 ≝ p in T' lft rgt).
697
698 lemma pair_destruct_1:
699  ∀A,B.∀a:A.∀b:B.∀c. 〈a,b〉 = c → a = \fst c.
700  #A #B #a #b *; /2/
701 qed.
702
703 lemma pair_destruct_2:
704  ∀A,B.∀a:A.∀b:B.∀c. 〈a,b〉 = c → b = \snd c.
705  #A #B #a #b *; /2/
706 qed.
707
708
709 let rec exclusive_disjunction (b: bool) (c: bool) on b ≝
710   match b with
711     [ true ⇒
712       match c with
713         [ false ⇒ true
714         | true ⇒ false
715         ]
716     | false ⇒
717       match c with
718         [ false ⇒ false
719         | true ⇒ true
720         ]
721     ].
722
723 (* dpm: conflicts with library definitions
724 interpretation "Nat less than" 'lt m n = (ltb m n).
725 interpretation "Nat greater than" 'gt m n = (gtb m n).
726 interpretation "Nat greater than eq" 'geq m n = (geb m n).
727 *)
728
729 let rec division_aux (m: nat) (n : nat) (p: nat) ≝
730   match ltb n (S p) with
731     [ true ⇒ O
732     | false ⇒
733       match m with
734         [ O ⇒ O
735         | (S q) ⇒ S (division_aux q (n - (S p)) p)
736         ]
737     ].
738     
739 definition division ≝
740   λm, n: nat.
741     match n with
742       [ O ⇒ S m
743       | S o ⇒ division_aux m m o
744       ].
745       
746 notation "hvbox(n break ÷ m)"
747   right associative with precedence 47
748   for @{ 'division $n $m }.
749   
750 interpretation "Nat division" 'division n m = (division n m).
751
752 let rec modulus_aux (m: nat) (n: nat) (p: nat) ≝
753   match leb n p with
754     [ true ⇒ n
755     | false ⇒
756       match m with
757         [ O ⇒ n
758         | S o ⇒ modulus_aux o (n - (S p)) p
759         ]
760     ].
761     
762 definition modulus ≝
763   λm, n: nat.
764     match n with
765       [ O ⇒ m
766       | S o ⇒ modulus_aux m m o
767       ].
768     
769 notation "hvbox(n break 'mod' m)"
770   right associative with precedence 47
771   for @{ 'modulus $n $m }.
772   
773 interpretation "Nat modulus" 'modulus m n = (modulus m n).
774
775 definition divide_with_remainder ≝
776   λm, n: nat.
777     pair ? ? (m ÷ n) (modulus m n).
778     
779 let rec exponential (m: nat) (n: nat) on n ≝
780   match n with
781     [ O ⇒ S O
782     | S o ⇒ m * exponential m o
783     ].
784
785 interpretation "Nat exponential" 'exp n m = (exponential n m).
786     
787 notation "hvbox(a break ⊎ b)"
788  left associative with precedence 50
789 for @{ 'disjoint_union $a $b }.
790 interpretation "sum" 'disjoint_union A B = (Sum A B).
791
792 theorem less_than_or_equal_monotone:
793   ∀m, n: nat.
794     m ≤ n → (S m) ≤ (S n).
795  #m #n #H
796  elim H
797  /2/
798 qed.
799
800 theorem less_than_or_equal_b_complete:
801   ∀m, n: nat.
802     leb m n = false → ¬(m ≤ n).
803  #m;
804  elim m;
805  normalize
806  [ #n #H
807    destruct
808  | #y #H1 #z
809    cases z
810    normalize
811    [ #H
812      /2/
813    | /3/
814    ]
815  ]
816 qed.
817
818 theorem less_than_or_equal_b_correct:
819   ∀m, n: nat.
820     leb m n = true → m ≤ n.
821  #m
822  elim m
823  //
824  #y #H1 #z
825  cases z
826  normalize
827  [ #H
828    destruct
829  | #n #H lapply (H1 … H) /2/
830  ]
831 qed.
832
833 definition less_than_or_equal_b_elim:
834  ∀m, n: nat.
835  ∀P: bool → Type[0].
836    (m ≤ n → P true) → (¬(m ≤ n) → P false) → P (leb m n).
837  #m #n #P #H1 #H2;
838  lapply (less_than_or_equal_b_correct m n)
839  lapply (less_than_or_equal_b_complete m n)
840  cases (leb m n)
841  /3/
842 qed.
843
844 lemma inclusive_disjunction_true:
845   ∀b, c: bool.
846     (orb b c) = true → b = true ∨ c = true.
847   # b
848   # c
849   elim b
850   [ normalize
851     # H
852     @ or_introl
853     %
854   | normalize
855     /2/
856   ]
857 qed.
858
859 lemma conjunction_true:
860   ∀b, c: bool.
861     andb b c = true → b = true ∧ c = true.
862   # b
863   # c
864   elim b
865   normalize
866   [ /2/
867   | # K
868     destruct
869   ]
870 qed.
871
872 lemma eq_true_false: false=true → False.
873  # K
874  destruct
875 qed.
876
877 lemma inclusive_disjunction_b_true: ∀b. orb b true = true.
878  # b
879  cases b
880  %
881 qed.
882
883 definition bool_to_Prop ≝
884  λb. match b with [ true ⇒ True | false ⇒ False ].
885
886 coercion bool_to_Prop: ∀b:bool. Prop ≝ bool_to_Prop on _b:bool to Type[0]. 
887
888 lemma eq_false_to_notb: ∀b. b = false → ¬ b.
889  *; /2/
890 qed.
891
892 lemma length_append:
893  ∀A.∀l1,l2:list A.
894   |l1 @ l2| = |l1| + |l2|.
895  #A #l1 elim l1
896   [ //
897   | #hd #tl #IH #l2 normalize \ 5ih ]="" qed.=""\ 6\ 5/ih\ 6\ 5/cons_prf\ 6\ 5/prfcr\ 6\ 5/refl_prf\ 6\ 5/cons_prf\ 6\ 5/prfcr\ 6\ 5/nil_prf\ 6\ 5/prfcr\ 6