定义具有类型参数约束的归纳依赖类型

时间:2015-08-20 14:07:16

标签: coq dependent-type

我尝试在Coq中定义一个归纳依赖类型来表示位向量逻辑中的位向量变量。

我读过Xavier Leroy的这个blog post,他在其中定义了如下结构:

Require Import Vector.

Inductive bitvector : Type := Bitvector (n: nat) (v: Vector.t bool n).

然后,为了测试这种做法,我尝试按如下方式定义按位求反运算符:

Definition bv_neg (v : bitvector) :=
    match v with
        Bitvector n w => Bitvector n (Vector.map negb w)
    end.

并且,开始证明应用两次否定相当于身份:

Lemma double_neg :
   forall (v : bitvector), (bv_neg (bv_neg v) = v).

但是,当我试图进行证明时,我意识到拥有零大小的位向量对于处理每个证明中的特殊情况n = 0没有任何意义和力量。

所以,我想知道如何强制归纳依赖型参数严格为正。

欢迎任何提示!

3 个答案:

答案 0 :(得分:7)

这样做的一种方法是确保存储的Vector大小为S n

Inductive bitvector : Type := Bitvector (n: nat) (v: Vector.t bool (S n)).

但是,我不明白为什么你想在这种特殊情况下这样做,因为这个引理是完全可证明的:这是一个相当简单的推论,可能是你可能更普遍的引理以后需要。

您的定义(没有S n更改):

Require Import Vector.

Inductive bitvector : Type := Bitvector (n: nat) (v: Vector.t bool n).

Definition bv_neg (v : bitvector) :=
    match v with
        Bitvector n w => Bitvector n (Vector.map negb w)
    end.

Vector.map上的一些结果:

Lemma map_fusion : 
  forall {A B C} {g : B -> C} {f : A -> B} {n : nat} (v : Vector.t A n),
    Vector.map g (Vector.map f v) = Vector.map (fun x => g (f x)) v.
Proof.
intros A B C g f n v ; induction v.
  - reflexivity.
  - simpl; f_equal; assumption.
Qed.

Lemma map_id : 
  forall {A} {n : nat} (v : Vector.t A n), Vector.map (@id A) v = v.
Proof.
intros A n v ; induction v.
  - reflexivity.
  - simpl; f_equal; assumption.
Qed.

Lemma map_extensional : 
  forall {A B} {f1 f2 : A -> B} 
         (feq : forall a, f1 a = f2 a) {n : nat} (v : Vector.t A n),
    Vector.map f1 v = Vector.map f2 v.
Proof.
intros A B f1 f2 feq n v ; induction v.
  - reflexivity.
  - simpl; f_equal; [apply feq | assumption].
Qed.

最后,你的结果:

Lemma double_neg :
   forall (v : bitvector), (bv_neg (bv_neg v) = v).
Proof.
intros (n, v).
 simpl; f_equal.
 rewrite map_fusion, <- map_id.
 apply map_extensional.
 - intros []; reflexivity.
Qed.

答案 1 :(得分:2)

为了确保我理解Arthur Azevedo De Amorim的评论,我试图重写我的Coq模块,试图去除语法糖和不必要的大小隐藏。

首先,只需查看Coq中的可用模块,就可以找到与我想要的非常接近的Coq.Bool.Bvector模块......但是,缺少很多(特别是模块化算术部分)和此外,我不同意一些规则,例如编码符号或具有真假,作为size = 1)的特定情况。

所以,我的模块几乎是Coq.Bool.Bvector的副本,但稍加修改就让我开心(我可能错了,我们将来会看到它)。

这是重写的模块:

Require Import Arith Bool Vector.

(** Unsigned Bitvector type *)
Definition bitvector := Vector.t bool.

Definition nil  := @Vector.nil bool.
Definition cons := @Vector.cons bool.

Definition bv_low := @Vector.hd bool.
Definition bv_high := @Vector.tl bool.

(** A bitvector is false if zero and true otherwise. *)
Definition bv_test n (v : bitvector n) := Vector.fold_left orb false v.

(** Bitwise operators *)
Definition bv_neg n (v : bitvector n) := Vector.map negb v.

Definition bv_and n (v w : bitvector n) := Vector.map2 andb v w.
Definition bv_or  n (v w : bitvector n) := Vector.map2  orb v w.
Definition bv_xor n (v w : bitvector n) := Vector.map2 xorb v w.

(** Shift/Rotate operators *)
(* TODO *)

(** Arithmetic operators *)
(* TODO *)

然后,我试图在Guillaume Allais提示的帮助下(再次)证明双重否定的事情:

Lemma map_fusion :
  forall {A B C} {g : B -> C} {f : A -> B} {n : nat} (v : Vector.t A n),
    Vector.map g (Vector.map f v) = Vector.map (fun x => g (f x)) v.
Proof.
intros A B C g f n v ; induction v.
  - reflexivity.
  - simpl; f_equal; assumption.
Qed.

Lemma map_id :
  forall {A} {n : nat} (v : Vector.t A n), Vector.map (@id A) v = v.
Proof.
intros A n v ; induction v.
  - reflexivity.
  - simpl; f_equal; assumption.
Qed.

Lemma map_extensional :
  forall {A B} {f1 f2 : A -> B}
         (feq : forall a, f1 a = f2 a) {n : nat} (v : Vector.t A n),
    Vector.map f1 v = Vector.map f2 v.
Proof.
intros A B f1 f2 feq n v ; induction v.
  - reflexivity.
  - simpl; f_equal; [apply feq | assumption].
Qed.

Theorem double_neg :
  forall (n : nat) (v : bitvector n), bv_neg n (bv_neg n v) = v.
Proof.
  intros; unfold bv_neg.
  rewrite map_fusion, <- map_id.
  apply map_extensional.
  - intros []; reflexivity.
Qed.

令人惊讶的是(对我来说),它就像一个魅力。

非常感谢所有人,如果您对此代码有任何意见,请随时发表评论。由于我对Coq很新,我真的想改进。

答案 2 :(得分:2)

你可以通过感应来证明这个定理 v

Require Import Vector.
Definition bitvector := Vector.t bool.
Definition bv_neg n (v : bitvector n) := Vector.map negb v.

Theorem double_neg :
  forall (n : nat) (v : bitvector n), bv_neg n (bv_neg n v) = v.
Proof.
  induction v as [|x]; [|simpl; destruct x; rewrite IHv]; reflexivity.
Qed.