当使用Program执行递归函数时Coq从if语句中丢失信息

时间:2017-05-10 16:21:42

标签: coq

我想简单地编写gcd的这个递归变体,"自然而然地#34;尽可能在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.

现在我需要证明b <> 0但我丢失了0 <? b = false分支中的信息。

  a, b : nat
  gcd : nat -> forall b0 : nat, b0 < b -> nat
  ============================
  b <> 0

如何保留if语句中的信息?

我知道我可以使用match,但是如何用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.

===编辑===

我注意到Coq(在更新版本中?)会记住0 <? b与匹配模式(本例中为truefalse)之间的关联。或者它是Program的一个特征?无论如何,我认为if基本上已经扩展到这个match声明,但显然它不是......

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.

1 个答案:

答案 0 :(得分:2)

可以使用lt_dec来做到这一点。

lt_dec
     : forall n m : nat, {n < m} + {~ n < m}

这样我们就可以在上下文中保留我们需要的证明,这与使用<?时不同,后者返回bool

Require Import Arith.
Require Import Program.

Program Fixpoint gcd (a b:nat) {measure b} :=
  if lt_dec 0 b then gcd b (a mod b) else a.
Next Obligation.
  apply Nat.mod_upper_bound.
  now destruct H.
Defined.

是的,它是Program的一项功能。实际上,参考手册以非常清晰的方式解释了它(见§24.1):

  

产生平等。 match表达式总是由相应的相等性推广。例如,表达式:

match x with
  | 0 => t
  | S n => u
  end.
     

将首先改写为:

(match x as y return (x = y -> _) with
| 0 => fun H : x = 0 -> t
| S n => fun H : x = S n -> u
end) (eq_refl n).

以下是if不同的原因:

  

为了更好地控制均等的生成,如果指定了returnin子句,则类型检查器将直接回退到Coq通常的依赖模式匹配类型。同样,if构造不会被Program专门处理,因此代码中的布尔测试不会自动反映在义务中。可以使用dec组合器来获得正确的假设,如:

Coq < Program Definition id (n : nat) : { x : nat | x = n } :=
        if dec (leb n 0) then 0
        else S (pred n).