证明唯一的零长度向量是零

时间:2017-12-22 17:48:39

标签: coq dependent-type

我有一个定义为

的类型
Inductive bits : nat -> Set :=
| bitsNil : bits 0
| bitsCons : forall {l}, bool -> bits l -> bits (S l).

我试图证明:

Lemma emptyIsAlwaysNil : forall {a: bits 0}, a = bitsNil.

intros之后,我已经尝试constructor 1case aintuition,但无济于事。 case a似乎是最接近的,但它会出错:

Abstracting over the terms "0" and "a" leads to a term
fun (n : nat) (a0 : bits n) => a0 = bitsNil
which is ill-typed.
Reason is: Illegal application: 
The term "@eq" of type "forall A : Type, A -> A -> Prop"
cannot be applied to the terms
 "bits n" : "Set"
 "a0" : "bits n"
 "bitsNil" : "bits 0"
The 3rd term has type "bits 0" which should be coercible to 
"bits n".

听起来它无法确定任意长度的位向量是否等于零长度的位向量,因为它们在类型级别上是不同的。这是对的吗?

2 个答案:

答案 0 :(得分:3)

是的,您基本上是正确的:具体来说,不是类型检查是Coq尝试在match上构建a:bits 0(这是{{1} 1}}确实):case案例有一个错误的结论。

这是一个没有公理的证明。关键的想法是手动将语句概括为任何bitsCons(我无法弄清楚如何使用策略来执行此操作;它们都会依赖于依赖关系)。然后,无论n = 0是什么,等式证明都会进行结论类型检查,我们可以解除n案例,因为我们有bitsCons。在更困难的n = S n'情况下,我们使用bitsNil,这是Axiom K的结果,但是当类型索引(在这种情况下为eq_rect_eq_dec)具有可判定的相等性时可以证明。如果没有具有可判定的相等性的公理,您可以查看Coq standard library documentation以了解其他一些事情。

nat

你不需要来自Require PeanoNat. Require Import Eqdep_dec. Import EqNotations. Inductive bits : nat -> Set := | bitsNil : bits 0 | bitsCons : forall {l}, bool -> bits l -> bits (S l). Lemma emptyIsAlwaysNil_general : forall n (H: n = 0) {a: bits n}, rew [bits] H in a = bitsNil. Proof. intros. induction a; simpl. (* bitsNil *) rewrite <- eq_rect_eq_dec; auto. apply PeanoNat.Nat.eq_dec. (* bitsCons - derive a contradiction *) exfalso; discriminate H. Qed. Lemma emptyIsAlwaysNil : forall {a: bits 0}, a = bitsNil. Proof. intros. change a with (rew [bits] eq_refl in a). apply emptyIsAlwaysNil_general. Qed. 的{​​{1}}符号(它只包含rew H in x,等式递归原理),但我发现它使事情更具可读性。< / p>

然而,如果你愿意使用公理,你可以更简单地证明这个定理,特别是EqNotations(更多细节参见CPDT's equality chapter),从那以后你可以使用{{1 }或eq_rect

JMeq_eq

答案 1 :(得分:2)

这是一个简单的证明(借鉴this Coq Club thread):

$opts = array(
    "replies" => array("Lock", "Locked"),
    "flagged" => array(null, "Ignore"),
    "deleted" => array("Delete", "Deleted")
);

foreach ($opts as $key => $values) {
    if ($row[$key] == 1) {
        echo "<input type=\"submit\" value=\"{$values[1]}\">";
    } else {
        if ($values[0]) { 
            echo "<input type=\"submit\" value=\"{values[0]}\">";
        }
    }
}

以下是Coq构建的内容:

Definition emptyIsAlwaysNil {a: bits 0} : a = bitsNil :=
  match a with bitsNil => eq_refl end.

Opaque emptyIsAlwaysNil.