证明Coq中的共同懒惰列表中的平等

时间:2016-10-05 19:53:21

标签: coq lazy-sequences coinduction

我正在尝试使用Coq Coinductive类型。我使用Coq'Art书中的懒惰列表类型(第13.1.4节):

Set Implicit Arguments.

CoInductive LList (A:Set) : Set :=
| LNil : LList A
| LCons : A -> LList A -> LList A.
Implicit Arguments LNil [A].

CoFixpoint LAppend (A:Set) (u v:LList A) : LList A :=
  match u with
  | LNil => v
  | LCons a u' => LCons a (LAppend u' v)
  end.

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

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)是公理不一致的吗?

2 个答案:

答案 0 :(得分:4)

你猜对了:就像功能一样,Coq的通用平等概念太弱而不适用于大多数共同类型。如果你想证明你的结果,你需要将SET NOCOUNT ON; DECLARE @t TABLE (i INT, sd NVARCHAR(MAX), ld NVARCHAR(MAX)); INSERT INTO @t VALUES (1, '', '1s. 2s. 3s. 4.'); INSERT INTO @t VALUES (2, '', '4s. 5s. 6s. 7.'); INSERT INTO @t VALUES (3, '', '6s. 7.'); DECLARE @sd NVARCHAR(MAX) DECLARE @ld NVARCHAR(MAX) DECLARE @i INT, @a INT; DECLARE @ss TABLE (s NVARCHAR(MAX)); DECLARE @s NVARCHAR(MAX); WHILE (SELECT COUNT(*) FROM @t) > 0 BEGIN SELECT TOP 1 @i = i, @sd = sd, @ld = ld FROM @t; DELETE FROM @ss; SET @a = 1 WHILE LEN(@ld) > 0 BEGIN IF @a > 3 BREAK; SET @s = LEFT(@ld, CHARINDEX('.', @ld)); INSERT INTO @ss VALUES (@s); SET @ld = REPLACE(@ld, @s, ''); SET @a = @a + 1; END WHILE (SELECT COUNT(*) FROM @ss) > 0 BEGIN SELECT TOP 1 @s = s FROM @ss; SET @sd = @sd + @s DELETE FROM @ss WHERE s = @s END PRINT @sd; DELETE FROM @t WHERE i = @i; END 替换为列表相等的共同概念;例如:

eq

操纵无限对象是Coq中的一个广泛主题。如果你想了解更多,亚当Chlipala的CPDT有一个完整的chapter coinduction。

答案 1 :(得分:2)

一个简单的规则是尽快在您的证明中使用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.

您实际应该交换introscofix。从那里,证明并不困难。

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

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.