I want to write this recursive variant of gcd
as simply and "naturally" as possible in Coq.
Require Import Arith.
Require Import Program.
Program Fixpoint gcd (a b:nat) {measure b} :=
if 0 <? b then gcd b (a mod b) else a.
Next Obligation.
(* Here I need to prove that `a mod b < b` *)
apply Nat.mod_upper_bound.
Now I need to prove that b <> 0
but I have lost the info that we are in the 0 <? b = false
branch.
a, b : nat
gcd : nat -> forall b0 : nat, b0 < b -> nat
============================
b <> 0
How do I keep the information from the if statement?
I know I could use match
, but how to I write it with if
?)
Program Fixpoint gcd (a b:nat) {measure b} :=
match b with 0 => a | S b' => gcd b (a mod b) end.
Next Obligation.
apply Nat.mod_upper_bound.
(* Goal: S b' <> 0 *)
congruence.
Defined.
=== EDIT ===
I noticed that Coq (in more recent versions?) remembers the association between 0 <? b
and the match patterns (true
or false
in this case). Or is it a feature of Program
? Anyway, I thought that if
essentially was expanded into this match
statement, but apparently it isn't...
Program Fixpoint gcd (a b:nat) {measure b} : nat:=
match 0<?b with
| true => gcd b (a mod b)
| false => a
end.
Next Obligation.
apply Nat.mod_upper_bound.
(* now we have ` true = (0 <? b)` in the assumptions, and the goal `b <> 0` *)
now destruct b.
Defined.