如何在Coq中以会员证明作为参数来实现删除?

时间:2019-06-02 14:13:34

标签: coq

data _∈_ {X : Set} (x : X) : (xs : List X) → Set where
  here! : {xs : List X} → x ∈ x ∷ xs
  there : {xs : List X} {y : X} (pr : x ∈ xs) → x ∈ y ∷ xs

remove : {X : Set} {x : X} (xs : List X) (pr : x ∈ xs) → List X
remove (_ ∷ xs) here!      = xs
remove (y ∷ xs) (there pr) = y ∷ remove xs pr

我试图将以上定义从阿格达(Agda)转换为考克(Coq),并且遇到了困难。

Inductive Any {A : Type} (P : A -> Type) : list A -> Prop :=
  | here : forall {x : A} {xs : list A}, P x -> Any P (x :: xs)
  | there : forall {x : A} {xs : list A}, Any P xs -> Any P (x :: xs).

Definition In' {A : Type} (x : A) xs := Any (fun x' => x = x') xs.

Fixpoint remove {A : Type} {x : A} {l : list A} (pr : In' x l) : list A :=
  match l, pr with
  | [], _ => []
  | _ :: ls, here _ _ => ls
  | x :: ls, there _ pr => x :: remove pr
  end.
Incorrect elimination of "pr0" in the inductive type "@Any":
the return type has sort "Type" while it should be "Prop".
Elimination of an inductive object of sort Prop
is not allowed on a predicate in sort Type
because proofs can be eliminated only to build proofs.

除了此错误外,如果我不提出[]案件,Coq会要求我提供它,尽管它很荒谬。

到目前为止,我认为Agda和Coq是相同的语言,但前端不同,但是现在我开始认为它们在幕后是不同的。有没有一种方法可以在Coq中复制删除功能,如果没有,您会推荐哪种选择?

编辑:我还希望将证明保留在InIn'之间。最初,我将In'设为Type,而不是Prop,但这使以下证明因类型错误而失败。

Fixpoint In {A : Type} (x : A) (l : list A) : Prop :=
  match l with
  | [] ⇒ False
  | x' :: l' ⇒ x' = x ∨ In x l'
  end.

Theorem In_iff_In' : 
  forall {A : Type} (x : A) (l : list A), 
  In x l <-> In' x l.
Proof. 
intros.
split.
- intros.
  induction l.
  + inversion H.
  + simpl in H.
    destruct H; subst.
    * apply here. reflexivity.
    * apply there. apply IHl. assumption.
- intros.
  induction H.
  + left. subst. reflexivity.
  + right. assumption.
Qed.
In environment
A : Type
x : A
l : list A
The term "In' x l" has type "Type" while it is expected to have type 
"Prop" (universe inconsistency).

此处的In来自SF的Logic chapter。我在Agda中有鸽子洞原理的解决方案,因此我希望将此双射转换为练习所要求的形式。

Edit2

Theorem remove_lemma :
  forall {A} {x} {y} {l : list A} (pr : In' x l) (pr' : In' y l),
  x = y \/ In' y (remove pr).

即使在定义Type时使用In',我也会在此定义中遇到Universe不一致的情况。

1 个答案:

答案 0 :(得分:2)

您需要使用会员资格证明。现在,您的AnyProp中取值,由于其消除的限制(请参阅错误消息),该值与公理forall (P: Prop) (x y: P), x = y是一致的。这意味着,如果您有某个术语依赖于其类型在Prop中的术语(remove就是这种情况),那么它只能使用存在该术语的事实,而不必使用具体来说。通常,您不能在Prop上使用消除(通常是模式匹配)来产生除Prop之外的任何东西。

In' 1 [1; 2; 1; 3; 1; 4]有三种本质上不同的证明,根据所使用的证明,remove p可以是[2; 1; 4; 1; 4][1; 2; 3; 1; 4][1; 2; 1; 3; 4]。因此,输出在本质上取决于特定的证明。

要解决此问题,您只需将Prop中的Inductive Any {A : Type} (P : A -> Type) : list A -> Prop替换为Type 1 现在我们可以消除为非Prop类型和您对remove的定义按书面规定进行。


要回答您的编辑,我认为最大的问题是您的某些定理/定义需要In'成为Prop(因为它们依赖于非信息量的证明),而另一些则需要信息量的证明。

我认为您最好的选择是将In'保留为Type,然后证明定理的非信息性版本。在标准库中,Coq.Init.Logic中有一个归纳类型inhabited

Inductive inhabited (A: Type): Prop :=
| inhabits: A -> inhabited A.

这是一种类型,本质上会忘记任何有关其术语的特定信息,只会记住它是否有人居住。我认为,只要将In' x l替换为inhabited (In' x l),就可以证明您的定理和引理。我能够证明您的定理的一个变体,其结论只是In x l <-> inhabited (In' x l)。您的证明大部分有效,但是我必须一步一步使用以下简单引理:

Lemma inhabited_there {A: Type} {P: A -> Type} {x: A} {xs: list A}:
  inhabited (Any P xs) -> inhabited (Any P (x :: xs)).

注意:尽管inhabited A基本上只是Prop的{​​{1}}版本,并且我们有A,但由于我们一般无法证明A -> inhabited A,因为这将涉及选择inhabited A -> A的任意元素。 2


  1. 我之前在这里也建议过A,但是由于归纳类型取决于Set中的A,因此无法使用。

  2. 事实上,我相信证明助理Lean会在选择公理中使用与此类似的东西。