Record 问:有没有可能证明,如果两个记录不同,那么其中一个字段就不同?

Record 问:有没有可能证明,如果两个记录不同,那么其中一个字段就不同?,record,coq,Record,Coq,假设你有记录: Record Example := { fieldA : nat; fieldB : nat }. 我们能否证明: Lemma record_difference : forall (e1 e2 : Example), e1 <> e2 -> (fieldA e1 <> fieldA e2) \/ (fieldB e1 <> fieldB e2). 另一方面,在不知道是什么使得e1首先不同于e2的情

假设你有记录:

Record Example := {
  fieldA : nat;
  fieldB : nat
}.
我们能否证明:

Lemma record_difference : forall (e1 e2 : Example),
  e1 <> e2 ->
    (fieldA e1 <> fieldA e2)
    \/
    (fieldB e1 <> fieldB e2).
另一方面,在不知道是什么使得
e1
首先不同于
e2
的情况下,我们应该如何决定要证明析取的哪一边

这正是问题的关键:我们需要弄清楚是什么让这两个记录有所不同。我们可以通过测试
fieldA e1=fieldA e2
来实现这一点

Require Import Coq.Arith.PeanoNat.

Record Example := {
  fieldA : nat;
  fieldB : nat
}.

Lemma record_difference : forall (e1 e2 : Example),
  e1 <> e2 ->
    (fieldA e1 <> fieldA e2)
    \/
    (fieldB e1 <> fieldB e2).
Proof.
intros [n1 m1] [n2 m2] He1e2; simpl.
destruct (Nat.eq_dec n1 n2) as [en|nen]; try now left.
right. intros em. congruence.
Qed.
{p}+{~p}
表示法表示一种特殊类型的布尔值,它可以根据其位于哪一侧,在解构时为
p
~p
提供证明

值得一步一步地通过这一证明来看看到底发生了什么。例如,在证明的第三行,执行
intros em
可以实现以下目标

n1, m1, n2, m2 : nat
He1e2 : {| fieldA := n1; fieldB := m1 |} <> {| fieldA := n2; fieldB := m2 |}
en : n1 = n2
em : m1 = m2
============================
False
相反,我们得到

forall (A B : Type) (p1 p2 : A * B),
  p1 <> p2 <-> ~ (fst p1 = fst p2 /\ snd p1 = snd p2).
forall(ab:Type)(p1p2:A*B),
p1p2~(fstp1=fstp2/\sndp1=sndp2)。

正是在这里,我们被困在没有可判定性假设的情况下。德摩根定律允许我们将右边转换为
~P\/~Q
形式的语句;然而,他们的证据诉诸于可判定性,这在Coq的建设性逻辑中并不普遍可用

可能值得注意的是,如果字段上没有可判定的等式,那么最好的方法是像
e1e2~(fieldA e1=fieldA e2/\fieldB e1=fieldB e2)
;可判定相等是从
~(A/\B)
~A\/~B
的方式。此外,不需要记录的所有字段都具有可判定相等来证明引理,只有
n-1
可判定字段就足够了(对于具有
n
字段的记录)。
n1, m1, n2, m2 : nat
He1e2 : {| fieldA := n1; fieldB := m1 |} <> {| fieldA := n2; fieldB := m2 |}
en : n1 = n2
em : m1 = m2
============================
False
forall (A B : Type) (p1 p2 : A * B),
  p1 = p2 <-> fst p1 = fst p2 /\ snd p1 = snd p2.
forall (A B : Type) (p1 p2 : A * B),
  p1 <> p2 <-> ~ (fst p1 = fst p2 /\ snd p1 = snd p2).