簡體   English   中英

Coq:在假設或目標中用'forall'重寫

[英]Coq: Rewriting with 'forall' in hypothesis or goal

我已經證明了Coq中多態列表的反函數的“正確性”。 以下證明工作正常,但我有一些關於重寫策略如何工作的問題。

這是代碼:

Require Export Coq.Lists.List.
Import ListNotations.

Fixpoint rev {T:Type} (l:list T) : list T :=
  match l with
  | nil    => nil
  | h :: t => rev t ++ [h]
  end.

(* Prove rev_acc equal to above naive implementation. *)
Fixpoint rev_acc {T:Type} (l acc:list T) : list T :=
  match l with
  | nil => acc
  | h :: t => rev_acc t (h::acc)
  end.

Theorem app_assoc : forall  (T:Type) (l1 l2 l3 : list T),
  (l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).
Proof.
Admitted.

Theorem rev_acc_correct : forall (T:Type) (l k :list T),
  rev l ++ k = rev_acc l k.
Proof.
  intros T l.
  induction l as [ | h l' IHl' ].
  - reflexivity.
  - simpl. 
    intro k.
    (* Why is "intro k" required for "rewrite -> app_assoc" *)
    (* But "rewrite -> IHl'" works regardless of "intro k".  *)
    (* generalize (rev l'), [h], k. *)
    rewrite -> app_assoc.
    simpl.
    rewrite -> IHl'.
    reflexivity.
Qed.

rev_acc_correct的證明的歸納步驟中,如果我跳過介紹k ,那么用app_assoc重寫抱怨它無法找到匹配的子項。

Found no subterm matching "(?M1058 ++ ?M1059) ++ ?M1060" in the current goal.

在這里,我認為是 在占位符名稱之前表示術語是約束的,在這種情況下,對於某些類型T ,它是類型為List T的類型; 並且由於目標中的rev l'[h]List T的實例,因此可以預期目標中的匹配。

另一方面,使用歸納假設( 重寫 - > IHl' )而不是app_assoc進行重寫 ,而不需要前面的介紹k

我發現這種重寫行為有點令人困惑,Coq手冊沒有提供任何細節。 我不想閱讀實現,但我需要對重寫策略的作用有一個良好的操作理解,特別是關於術語匹配如何工作。 任何在這個方向的答案/參考都非常感謝。

這種重寫的復雜性在於有一個綁定器forall k ),它可以使事情變得復雜。 如果你只是想要工作,使用setoid_rewrite而不是rewrite ,它將在綁定器下重寫。

  • rewrite IHl'看起來像是在綁定器下發生,但rewrite IHl'的模式實際上並不涉及綁定變量,因此綁定器實際上並不重要。 這就是我的意思:目標是

     forall k : list T, (rev l' ++ [h]) ++ k = rev_acc l' (h :: k) 

    這與(即等於)相同:

      (fun l : list T => forall k : list T, l ++ k = rev_acc l' (h :: k)) (rev l' ++ [h]) 

    我在Ltac中使用了pattern (rev l' ++ [h]) 現在很明顯,您可以只重寫正在應用的部分並忽略活頁夾。 當你rewrite IHl'時,很容易發現IHl應該專門用於[h]並且重寫繼續進行。

  • 另一方面, rewrite app_assoc需要專門針對三個列表,特別是rev l'[h]k 它不能專門用於當前上下文,因為變量k僅綁定在forall下面。 這就是為什么模式(?x ++ ?y) ++ ?z沒有出現在目標中。

那你究竟做了什么? 你當然可以介紹k所以沒有綁定器,但有一種更簡單,更通用的技術:Coq具有可以在綁定器下重寫的通用重寫,你可以使用它來代替調用setoid_rewrite (參見Coq參考手冊中的綁定下重寫 ) 。 手冊告訴你需要聲明態射,但是在這種情況下相關的已經為你實現了forall ,所以setoid_rewrite app_assoc將正常工作。

請注意,雖然你總是可以引入一個forall來擺脫綁定, setoid_rewrite當你的目標exists時, setoid_rewrite可以非常方便。 您可以在綁定器下重寫,而不是使用eexists

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM