coq - 二阶统一与重写

标签 coq unification rewriting

我有一个如下引理,带有一个高阶参数:

Require Import Coq.Lists.List.

Lemma map_fst_combine:
  forall A B C (f : A -> C) (xs : list A) (ys : list B),
  length xs = length ys ->
  map (fun p => f (fst p)) (combine xs ys) = map f xs. 
Proof.
  induction xs; intros.
  * destruct ys; try inversion H.
    simpl. auto.
  * destruct ys; try inversion H.
    simpl. rewrite IHxs; auto.
Qed.

我想将它与 rewrite 一起使用。如果我直接指定 f 就可以了:

Parameter list_fun : forall {A}, list A -> list A.
Parameter length_list_fun : forall A (xs : list A), length (list_fun xs) = length xs.

Lemma this_works:
  forall (xs : list bool),
  map (fun p => negb (negb (fst p))) (combine xs (list_fun xs)) =  xs.
Proof.
  intros.
  rewrite map_fst_combine with (f := fun x => negb (negb x))
    by (symmetry; apply length_list_fun).
Admitted. 

但我真的不想这样做(在我的例子中,我想将这个引理用作 autorewrite 集的一部分)。但是

Lemma this_does_not:
  forall (xs : list bool),
  map (fun p => negb (negb (fst p))) (combine xs (list_fun xs)) =  xs.
Proof.
  intros.
  rewrite map_fst_combine.

失败

(* 
Error:
Found no subterm matching "map (fun p : ?M928 * ?M929 => ?M931 (fst p))
                             (combine ?M932 ?M933)" in the current goal.
*)

我是不是期望太高了,还是有办法让它发挥作用?

最佳答案

让我们定义组合运算符(或者您可能想重用 Coq.Program.Basics 中定义的运算符):

Definition comp {A B C} (g : B -> C) (f : A -> B) :=
  fun x : A => g (f x).
Infix "∘" := comp (at level 90, right associativity).

现在,让我们根据组合来制定map_fst_combine 引理:

Lemma map_fst_combine:
  forall A B C (f : A -> C) (xs : list A) (ys : list B),
  length xs = length ys ->
  map (f ∘ fst) (combine xs ys) = map f xs.
Admitted.   (* the proof remains the same *)

现在我们需要一些autorewrite 的辅助引理:

Lemma map_comp_lassoc A B C D xs (f : A -> B) (g : B -> C) (h : C -> D) :
  map (fun x => h (g (f x))) xs = map ((h ∘ g) ∘ f) xs.
Proof. reflexivity. Qed.

Lemma map_comp_lassoc' A B C D E xs (f : A -> B) (g : B -> C) (h : C -> D) (i : D -> E) :
  map (i ∘ (fun x => h (g (f x)))) xs = map ((i ∘ h) ∘ (fun x => g (f x))) xs.
Proof. reflexivity. Qed.

有以下提示

Hint Rewrite map_comp_lassoc map_comp_lassoc' map_fst_combine : mapdb.

我们能够进行自动重写并摆脱 fstcombine:

Lemma autorewrite_works xs :
  map (fun p => negb (negb (fst p))) (combine xs (list_fun xs)) = xs.
Proof.
  autorewrite with mapdb.
  (* 1st subgoal: map (negb ∘ negb) xs = xs *)
Admitted.

Lemma autorewrite_works' xs :
  map (fun p => negb (negb (negb (negb (fst p))))) (combine xs (list_fun xs)) = xs.
Proof.
  autorewrite with mapdb.
  (* 1st subgoal: map (((negb ∘ negb) ∘ negb) ∘ negb) xs = xs *)
Admitted.

关于coq - 二阶统一与重写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44805518/

相关文章:

coq - 使用整数定理证明自然数定理

algorithm - 什么是统一算法?

scala - 有条件地重写 Kiama/Scala 中的术语

coq - 在 Coq 中使用 eexists 构造记录项

coq - 匹配策略/策略符号内的上下文模式

typeclass - Coq:展开类实例

functional-programming - 自底向上 Hindley-Milner 类型推断 : Applying a substitution to an implicit constraint

prolog - 统一术语顺序重要吗?

Coq:在 if-then-else 下重写

Agda:在类型定义中重写而不是显式强制转换?