Coq中关于共导惰性列表的等式证明

Coq中关于共导惰性列表的等式证明,coq,lazy-sequences,coinduction,Coq,Lazy Sequences,Coinduction,我正在试验Coq共导类型。我使用Coq'Art手册中的懒惰列表类型(第13.1.4节): 为了匹配保护条件,我还使用了本书中的以下分解函数: Definition LList_decomp (A:Set) (l:LList A) : LList A := match l with | LNil => LNil | LCons a l' => LCons a l' end. Lemma LList_decompose : forall (A:Set) (l:LLis

我正在试验Coq共导类型。我使用Coq'Art手册中的懒惰列表类型(第13.1.4节):

为了匹配保护条件,我还使用了本书中的以下分解函数:

Definition LList_decomp (A:Set) (l:LList A) : LList A :=
  match l with
  | LNil => LNil
  | LCons a l' => LCons a l'
  end.


Lemma LList_decompose : forall (A:Set) (l:LList A), l = LList_decomp l.
Proof.
 intros.
 case l.
 simpl.
 reflexivity.
 intros.
 simpl. 
 reflexivity.
Qed.
LNil
是左中性的引理很容易证明:

Lemma LAppend_LNil : forall (A:Set) (v:LList A), LAppend LNil v = v.
Proof.
 intros A v.
 rewrite LList_decompose with (l:= LAppend LNil v).
 case v.
 simpl.
 reflexivity.
 intros.
 simpl.
 reflexivity.
Qed.
但我被证明
LNil
也是正确中性的问题困住了:

Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LAppend v LNil = v.
在亚瑟的回答之后,我尝试了新的平等:

Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LListEq  (LAppend v LNil)  v.
Proof.
 intros.
 cofix.
 destruct v.
 rewrite LAppend_LNil.
 apply LNilEq.
我被卡住了。Coq的答案是:

1 subgoal
A : Set
a : A
v : LList A
LAppend_v_LNil : LListEq (LAppend (LCons a v) LNil) (LCons a v)
______________________________________(1/1)
LListEq (LAppend (LCons a v) LNil) (LCons a v)
在Eponier的回答之后,我想通过引入可扩展性公理对其进行最后的润色:

Axiom LList_ext: forall (A:Set)(l1 l2: LList A), (LListEq l1 l2 ) -> l1 = l2.
根据这个公理,我得到了引理的最后一个切分:

Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), (LAppend v LNil) = v.
Proof.
 intros.
 apply LList_ext.
 revert v.
   cofix.
   intros.
   destruct v. Guarded. (* now we can safely destruct v *)
   - rewrite LAppend_LNil.
     constructor.
   - rewrite (LList_decompose (LAppend _ _)).
     simpl. constructor. apply LAppend_v_LNil.
Qed.
现在,这是我在这篇文章中的最后几个问题:

  • 这种公理是否已经存在于某些Coq库中
  • 这个公理和Coq一致吗
  • 与Coq的哪些标准公理(例如经典、UIP、趣味分机、Streicher K)不一致

您猜对了:就像函数一样,Coq的通用相等概念太弱,无法用于大多数共导类型。如果你想证明你的结果,你需要用列表相等的共同归纳概念来取代
eq
;例如:

CoInductive LListEq (A:Set) : LList A -> LList A -> Prop :=
| LNilEq : LListEq A LNil LNil
| LConsEq x lst1 lst2 : LListEq A lst1 lst2 -> 
  LListEq A (LCons x lst1) (LCons x lst2).

操纵无限对象在Coq中是一个广泛的话题。如果你想了解更多,Adam Chlipala的CPDT有一个完整的共归纳法。

一个简单的规则是在你的证明中尽快使用
cofix

实际上,在您的
LAppend_v_LNil
证明中,在
destruct v
中已经违反了保护条件。您可以使用命令
Guarded
检查这一事实,这有助于在证明结束前测试是否所有的共归纳假设都是合法的

Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LListEq  (LAppend v LNil)  v.
  intros.
  cofix.
  destruct v. Fail Guarded.
Abort.
实际上,您应该交换
intros
cofix
。从那里,证明并不困难

编辑:这是完整的解决方案

Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LListEq (LAppend v LNil)  v.
  cofix.
  intros.
  destruct v. Guarded. (* now we can safely destruct v *)
  - rewrite LAppend_LNil.
    constructor.
  - rewrite (LList_decompose (LAppend _ _)).
    simpl. constructor. apply LAppend_v_LNil.
Qed.

非常感谢。我用新的等式扩展了这个问题。如果你能发布你的解决方案,那就太好了。最近有人在网站上问过类似的问题。(截至发表此评论时)还没有人回答。
Lemma LAppend_v_LNil : forall (A:Set) (v:LList A), LListEq (LAppend v LNil)  v.
  cofix.
  intros.
  destruct v. Guarded. (* now we can safely destruct v *)
  - rewrite LAppend_LNil.
    constructor.
  - rewrite (LList_decompose (LAppend _ _)).
    simpl. constructor. apply LAppend_v_LNil.
Qed.