|
| 1 | +Set Implicit Arguments. |
| 2 | +Require Import Omega. |
| 3 | +Require Import Coq.Numbers.Natural.Peano.NPeano. (* [mod] *) |
| 4 | +Require Import Coq.Arith.Wf_nat. (* [lt_wf] *) |
| 5 | +Require Import Coq.Wellfounded.Inclusion. (* [wf_incl] *) |
| 6 | +Require Import Coq.Wellfounded.Inverse_Image. (* [wf_inverse_image] *) |
| 7 | +Require Import Coq.Arith.Peano_dec. (* [eq_nat_dec] *) |
| 8 | +Require Import Recdef. |
| 9 | + |
| 10 | +(* This demos the use of [Function] instead of the [Loop] library. *) |
| 11 | + |
| 12 | +(* ---------------------------------------------------------------------------- *) |
| 13 | + |
| 14 | +(* Use OCaml integers at extraction time. *) |
| 15 | + |
| 16 | +Require Import ExtrOcamlNatInt. |
| 17 | +Extract Inlined Constant modulo => "(mod)". |
| 18 | +Extract Inlined Constant plus => "(+)". |
| 19 | + |
| 20 | +(* ---------------------------------------------------------------------------- *) |
| 21 | + |
| 22 | +(* Demo 1. Euclid's GCD algorithm. *) |
| 23 | + |
| 24 | +Function gcd (a : nat) (b : nat) { wf lt b } : nat := |
| 25 | + if eq_nat_dec b 0 then |
| 26 | + a |
| 27 | + else |
| 28 | + gcd b (a mod b). |
| 29 | +Proof. |
| 30 | + (* 1 *) |
| 31 | + intros a b ? _. eauto using Nat.mod_upper_bound. |
| 32 | + (* 2 *) |
| 33 | + eapply lt_wf. |
| 34 | +Qed. |
| 35 | + |
| 36 | +(* The extracted code is good. *) |
| 37 | +Extraction gcd. |
| 38 | + |
| 39 | +(* And we get the following proof principles. *) |
| 40 | +(* |
| 41 | +Check gcd_ind. |
| 42 | +Check gcd_rec. |
| 43 | +Check gcd_rect. |
| 44 | +Check gcd_equation. |
| 45 | +*) |
| 46 | + |
| 47 | +(* ---------------------------------------------------------------------------- *) |
| 48 | + |
| 49 | +(* GCD can also be defined using [Program]. *) |
| 50 | + |
| 51 | +Require Coq.Program.Program. |
| 52 | + |
| 53 | +Program Fixpoint GCD (a : nat) (b : nat) { wf lt b } : nat := |
| 54 | + if eq_nat_dec b 0 then |
| 55 | + a |
| 56 | + else |
| 57 | + GCD b (a mod b). |
| 58 | +Next Obligation. |
| 59 | + eauto using Nat.mod_upper_bound. |
| 60 | +Qed. |
| 61 | + |
| 62 | +(* The extracted code is kind of OK but not very readable. Some |
| 63 | + wrapping and unwrapping of pairs is taking place. *) |
| 64 | +Extract Inductive sigT => "( * )" [ "" ]. |
| 65 | +Extraction Inline projT1 projT2. |
| 66 | +Extraction GCD_func. |
| 67 | + |
| 68 | +Program Fixpoint GCD_alt (ab : nat * nat) { wf (fun (ab ab' : nat * nat) => lt (fst ab) (fst ab')) ab } : nat := |
| 69 | + let (a, b) := ab in |
| 70 | + if eq_nat_dec b 0 then |
| 71 | + a |
| 72 | + else |
| 73 | + GCD b (a mod b). |
| 74 | +Next Obligation. |
| 75 | + unfold Wf.MR. |
| 76 | + eapply wf_inverse_image. |
| 77 | + eapply lt_wf. |
| 78 | +Defined. |
| 79 | + |
| 80 | +(* Here, the extracted code is good. *) |
| 81 | +Extraction GCD_alt. |
| 82 | + |
| 83 | +(* ---------------------------------------------------------------------------- *) |
| 84 | + |
| 85 | +(* Demo 2. Counting up to 100, two by two. I don't know how to do this using |
| 86 | + [Function]. If one attempts to work directly with inhabitants of a subset |
| 87 | + type, one ends up having to write complicated proof terms, dependent [if]'s, |
| 88 | + etc. *) |
| 89 | + |
0 commit comments