对于Coq中的异构列表,可以证明Forall_inv的等价性吗?
在Adam Chlipala的异构列表之后,我想在普通列表上定义一个与所有函数等价的函数。这并不太难,你会像往常一样得到两个构造函数。现在假设我知道关于非空列表中的每个元素都有一个事实。对于普通列表,我可以使用对于Coq中的异构列表,可以证明Forall_inv的等价性吗?,coq,dependent-type,Coq,Dependent Type,在Adam Chlipala的异构列表之后,我想在普通列表上定义一个与所有函数等价的函数。这并不太难,你会像往常一样得到两个构造函数。现在假设我知道关于非空列表中的每个元素都有一个事实。对于普通列表,我可以使用Forall\u inv和Forall\u inv\u tail来断言列表的开头和结尾是正确的 我想证明如下定义的hForall的等效性,首先从头部案例开始。查看中的源代码,正常列表的证明很简单,并且通过对所有(a::l)的进行反转来运行。myhForall的等价项给出了一堆因变量。我错过
Forall\u inv
和Forall\u inv\u tail
来断言列表的开头和结尾是正确的
我想证明如下定义的hForall
的等效性,首先从头部案例开始。查看中的源代码,正常列表的证明很简单,并且通过对所有(a::l)的进行反转来运行。myhForall
的等价项给出了一堆因变量。我错过了什么明显的东西吗
Require Import List.
Section hlist.
Variable A : Type.
Variable B : A -> Type.
Inductive hlist : list A -> Type :=
| HNil : hlist nil
| HCons {a : A} {ls : list A} : B a -> hlist ls -> hlist (a :: ls).
Section hForall.
Variable P : forall a : A, B a -> Prop.
Inductive hForall : forall {As : list A}, hlist As -> Prop :=
| hForall_nil : hForall HNil
| hForall_cons {a : A} {ls : list A} (x : B a) (hl : hlist ls)
: P a x -> hForall hl -> hForall (HCons x hl).
Lemma hForall_inv
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall (HCons x hl) -> P a x.
Proof.
(* Help! *)
Abort.
End hForall.
End hlist.
按索引类型索引的归纳法会导致这种困难
另一方面,考虑将代码< > HFALALL < /代码>定义为<代码>不动点< /代码>。然后,逆引理只是展开定义
Section hForall'.
Variable P : forall a, B a -> Prop.
Fixpoint hForall' {As : list A} (hs : hlist As) : Prop :=
match hs with
| HNil => True
| HCons x js => P _ x /\ hForall' js
end.
Lemma hForall'_inv
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall' (HCons x hl) -> P a x.
Proof.
intros []; auto.
Qed.
End hForall'.
附录
主要出于教育目的,这里有几种方法来证明hForall
的原始归纳定义的反转引理(从更简单的使用开始)
一种解决方案是依赖销毁
策略,它也自动处理异构均衡,而不是销毁
。它是从程序
模块导入的:
Import Program.
Lemma hForall_inv
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall (HCons x hl) -> P a x.
Proof.
intros H.
dependent destruction H.
auto.
Qed.
(次要)问题是它使用了一些关于异构相等的公理:
Print Assumptions hForall_inv.
(*
Section Variables:
P : forall a : A, B a -> Prop
B : A -> Type
A : Type
Axioms:
Eqdep.Eq_rect_eq.eq_rect_eq : forall (U : Type) (p : U)
(Q : U -> Type) (x : Q p)
(h : p = p), x = eq_rect p Q x p h
JMeq_eq : forall (A : Type) (x y : A), x ~= y -> x = y
*)
通过对destruct
如何工作/依赖模式匹配的更多了解,这里有一个没有公理的证明
在CPDT中有一些关于依赖模式匹配的详细解释,但简单地说,问题是当我们在hForall(HCons x hl)
上进行destruct
/inversion
时,索引HCons x hl
在案例分割之前得到推广,因此,在一个无意义的情况下,它被替换为HNilHNil
,第二个情况下,它被替换为不同的索引HCons x0 hl0
,记住整个泛化过程中(异构)相等性的好方法是一个研究级问题。如果目标只是用这些变量重写的话,你就不需要处理异构等式了,事实上,你可以重构目标,使其明确地依赖于HCons x hl
,而不是分别依赖于x
和hl
,然后通过destruct
来概括:
Lemma hForall_inv'
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall (HCons x hl) -> P a x.
Proof.
intros H.
change (match HCons x hl return Prop with (* for some reason you have to explicitly annotate the return type as Prop right here *)
| HNil => True
| HCons x _ => P _ x
end).
destruct H.
- exact I. (* Replace [HCons x hl] with [HNil], the goal reduces to [True]. (This is an unreachable case.) *)
- assumption.
(* Or, directly writing down the proof term. *)
Restart.
intros H.
refine (match H in @hForall As hs return
match hs return Prop with
| HNil => True
| HCons x _ => P _ x
end
with
| hForall_nil => I
| hForall_cons _ _ _ _ => _
end).
assumption.
Qed.
公式插件可能会正确地自动执行,但我没有尝试过。按索引类型索引的归纳法会导致这种困难
另一方面,考虑将代码< > HFALALL < /代码>定义为<代码>不动点< /代码>。然后,逆引理只是展开定义
Section hForall'.
Variable P : forall a, B a -> Prop.
Fixpoint hForall' {As : list A} (hs : hlist As) : Prop :=
match hs with
| HNil => True
| HCons x js => P _ x /\ hForall' js
end.
Lemma hForall'_inv
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall' (HCons x hl) -> P a x.
Proof.
intros []; auto.
Qed.
End hForall'.
附录
主要出于教育目的,这里有几种方法来证明hForall
的原始归纳定义的反转引理(从更简单的使用开始)
一种解决方案是依赖销毁
策略,它也自动处理异构均衡,而不是销毁
。它是从程序
模块导入的:
Import Program.
Lemma hForall_inv
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall (HCons x hl) -> P a x.
Proof.
intros H.
dependent destruction H.
auto.
Qed.
(次要)问题是它使用了一些关于异构相等的公理:
Print Assumptions hForall_inv.
(*
Section Variables:
P : forall a : A, B a -> Prop
B : A -> Type
A : Type
Axioms:
Eqdep.Eq_rect_eq.eq_rect_eq : forall (U : Type) (p : U)
(Q : U -> Type) (x : Q p)
(h : p = p), x = eq_rect p Q x p h
JMeq_eq : forall (A : Type) (x y : A), x ~= y -> x = y
*)
通过对destruct
如何工作/依赖模式匹配的更多了解,这里有一个没有公理的证明
在CPDT中有一些关于依赖模式匹配的详细解释,但简单地说,问题是当我们在hForall(HCons x hl)
上进行destruct
/inversion
时,索引HCons x hl
在案例分割之前得到推广,因此,在一个无意义的情况下,它被替换为HNilHNil
,第二个情况下,它被替换为不同的索引HCons x0 hl0
,记住整个泛化过程中(异构)相等性的好方法是一个研究级问题。如果目标只是用这些变量重写的话,你就不需要处理异构等式了,事实上,你可以重构目标,使其明确地依赖于HCons x hl
,而不是分别依赖于x
和hl
,然后通过destruct
来概括:
Lemma hForall_inv'
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall (HCons x hl) -> P a x.
Proof.
intros H.
change (match HCons x hl return Prop with (* for some reason you have to explicitly annotate the return type as Prop right here *)
| HNil => True
| HCons x _ => P _ x
end).
destruct H.
- exact I. (* Replace [HCons x hl] with [HNil], the goal reduces to [True]. (This is an unreachable case.) *)
- assumption.
(* Or, directly writing down the proof term. *)
Restart.
intros H.
refine (match H in @hForall As hs return
match hs return Prop with
| HNil => True
| HCons x _ => P _ x
end
with
| hForall_nil => I
| hForall_cons _ _ _ _ => _
end).
assumption.
Qed.
“方程式”插件可能正确地自动化了这一点,但我没有尝试过。我认为解决这种破坏的最简单方法是告诉Coq我们关心这些破坏的模式。
或者,你们可以使用记忆策略,但有时它会使你们的定理更加难以解释
Lemma hForall_inv
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall (HCons x hl) -> P a x.
Proof.
have : forall (F : forall (a : A) (ls : list A) (x : B a) (hl : hlist ls) (H : hForall (HCons x hl)), Prop),
(forall (a : A) (ls : list A) (x : B a) (hl : hlist ls) (H : hForall (HCons x hl)) (I : forall (a : A) (ls : list A) (x : B a) (hl : hlist ls) (f : P a x) (H : hForall (HCons x hl)), F a ls x hl H),
F a ls x hl H).
intros.
refine (match H in (hForall (HCons x hl)) return F _ _ _ _ H with
|hForall_nil => _
|hForall_cons a x y z => _
end).
exact idProp.
exact (I _ _ _ _ y (hForall_cons a x y z)).
move => forall_rect.
elim/forall_rect; by [].
Qed.
我使用类型来实现消除的观察:
Inductive hForall : forall {As : list A}, hlist As -> Type :=
| hForall_nil : hForall HNil
| hForall_cons {a : A} {ls : list A} (x : B a) (hl : hlist ls)
: P a x -> hForall hl -> hForall (HCons x hl).
我认为解决这种破坏的最简单方法是告诉Coq我们关心这些破坏的模式。
或者,你们可以使用记忆策略,但有时它会使你们的定理更加难以解释
Lemma hForall_inv
(a : A)
(ls : list A)
(x : B a)
(hl : hlist ls)
: hForall (HCons x hl) -> P a x.
Proof.
have : forall (F : forall (a : A) (ls : list A) (x : B a) (hl : hlist ls) (H : hForall (HCons x hl)), Prop),
(forall (a : A) (ls : list A) (x : B a) (hl : hlist ls) (H : hForall (HCons x hl)) (I : forall (a : A) (ls : list A) (x : B a) (hl : hlist ls) (f : P a x) (H : hForall (HCons x hl)), F a ls x hl H),
F a ls x hl H).
intros.
refine (match H in (hForall (HCons x hl)) return F _ _ _ _ H with
|hForall_nil => _
|hForall_cons a x y z => _
end).
exact idProp.
exact (I _ _ _ _ y (hForall_cons a x y z)).
move => forall_rect.
elim/forall_rect; by [].
Qed.
我使用类型来实现消除的观察:
Inductive hForall : forall {As : list A}, hlist As -> Type :=
| hForall_nil : hForall HNil
| hForall_cons {a : A} {ls : list A} (x : B a) (hl : hlist ls)
: P a x -> hForall hl -> hForall (HCons x hl).
啊,我明白了。非常感谢你的提示-我会用它的!关于归纳法和索引类型的一般性陈述是有道理的,但我想知道更多关于可能出错的地方——是否有论文或类似的文章?遗憾的是,我不熟悉有关该主题的文献,我是根据个人经验做出这一陈述的。我确实有一些归纳版本的证据,我很快会补充到我的答案中。啊,我明白了。非常感谢你的提示-我会用它的!关于归纳法和索引类型的一般性陈述是有道理的,但我想知道更多关于可能出错的地方——是否有论文或类似的文章?遗憾的是,我不熟悉有关该主题的文献,我是根据个人经验做出这一陈述的。我确实有一些归纳版本的证据,我将很快添加到我的答案中。