对于Coq中的异构列表,可以证明Forall_inv的等价性吗?

对于Coq中的异构列表,可以证明Forall_inv的等价性吗?,coq,dependent-type,Coq,Dependent Type,在Adam Chlipala的异构列表之后,我想在普通列表上定义一个与所有函数等价的函数。这并不太难,你会像往常一样得到两个构造函数。现在假设我知道关于非空列表中的每个元素都有一个事实。对于普通列表,我可以使用Forall\u inv和Forall\u inv\u tail来断言列表的开头和结尾是正确的 我想证明如下定义的hForall的等效性,首先从头部案例开始。查看中的源代码,正常列表的证明很简单,并且通过对所有(a::l)的进行反转来运行。myhForall的等价项给出了一堆因变量。我错过

在Adam Chlipala的异构列表之后,我想在普通列表上定义一个与所有函数等价的函数。这并不太难,你会像往常一样得到两个构造函数。现在假设我知道关于非空列表中的每个元素都有一个事实。对于普通列表,我可以使用
Forall\u inv
Forall\u inv\u tail
来断言列表的开头和结尾是正确的

我想证明如下定义的
hForall
的等效性,首先从头部案例开始。查看中的源代码,正常列表的证明很简单,并且通过对所有(a::l)的
进行反转来运行。my
hForall
的等价项给出了一堆因变量。我错过了什么明显的东西吗

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
在案例分割之前得到推广,因此,在一个无意义的情况下,它被替换为HNil
HNil
,第二个情况下,它被替换为不同的索引
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
在案例分割之前得到推广,因此,在一个无意义的情况下,它被替换为HNil
HNil
,第二个情况下,它被替换为不同的索引
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).

啊,我明白了。非常感谢你的提示-我会用它的!关于归纳法和索引类型的一般性陈述是有道理的,但我想知道更多关于可能出错的地方——是否有论文或类似的文章?遗憾的是,我不熟悉有关该主题的文献,我是根据个人经验做出这一陈述的。我确实有一些归纳版本的证据,我很快会补充到我的答案中。啊,我明白了。非常感谢你的提示-我会用它的!关于归纳法和索引类型的一般性陈述是有道理的,但我想知道更多关于可能出错的地方——是否有论文或类似的文章?遗憾的是,我不熟悉有关该主题的文献,我是根据个人经验做出这一陈述的。我确实有一些归纳版本的证据,我将很快添加到我的答案中。