簡體   English   中英

如何使用重寫策略指定位置?

[英]How to specify a location with the rewrite tactic?

我對列表有一個簡單的引理,它說n::l = [n]++l其證明如下。

Lemma cons_to_app : (forall (n: nat) (l: list nat),  n :: l = [n] ++ l).
Proof.
  simpl. reflexivity.
Qed.

現在,我想使用此證明重寫缺點術語::無論它們出現在證明目標中的何處。 例如,考慮以下。

Lemma easy_lemma : forall (n : nat) (xs ys : list nat), (n::xs) ++ (n::ys) = (n::xs) ++ ([n] ++ ys).

我想將(n::ys)重寫為[n] ++ ys並完成證明。 由於n::ys是第二次::出現在證明目標,我認為rewrite const_to_app at 2會的工作,但實際上它作用於3 ::並更改證明目標(n :: xs) ++ n :: ys = ([n] ++ xs) ++ [n] ++ ys

我可以指定哪個位置以使重寫在(n::ys)項上起作用?

我仍然找不到談論rewrite at的確切行為的原始資源( 提到的一個eponier除外 )。 鏈接上的帖子寫於2011年,但對於Coq版本8.9.1而言,它似乎在2019年仍然有效,並且可能不會被“修復”,因為該問題已被關閉為“無效”,並說“改變行為會中斷”。向后兼容”。


問題

rewrite lemma at n使用第一個出現實例化等式,然后重寫第n個出現。

給定引理證明

Lemma easy_lemma :
  forall (n : nat) (xs ys : list nat), (n::xs) ++ (n::ys) = (n::xs) ++ ([n] ++ ys).

和用於重寫的引理

Lemma cons_to_app : (forall (n: nat) (l: list nat),  n :: l = [n] ++ l).

rewrite cons_to_app at n. 總是挑選subterm n :: xs ,然后重寫的第n次出現n :: xs[n] ++ xs 第二個n :: xs恰好是第三個_ :: _

解決方案

一個簡單的解決方案是提供足夠的參數來告訴Coq要重寫的確切內容。 在這種情況下, rewrite (cons_to_app _ ys)就足夠了。

一種替代方法是使用setoid_rewrite策略,該策略查看所有適用的子項。 但是,有時候對定義的理解太深了,這個例子的確如此。 setoid_rewrite cons_to_app at 1.

1 subgoal
n : nat
xs, ys : list nat
______________________________________(1/1)
[n] ++
(fix app (l m : list nat) {struct l} : list nat := match l with
                                                   | [] => m
                                                   | a :: l1 => a :: app l1 m
                                                   end) xs (n :: ys) = (n :: xs) ++ [n] ++ ys

折疊app會得到[n] ++ (xs ++ n :: ys) ,這與我們想要的結果不同,即([n] ++ xs) ++ n :: ys 我們可以觀察到一次setoid_rewrite展開的app ,將LHS更改為n :: (xs ++ n :: ys) ,然后實例化引理來重寫最外面的_ :: _

為避免app展開,我們可以聲明Opaque app. 重寫之前。 然后setoid_rewrite ... at 1給出我們想要的( at 2也是如此)。 要恢復Opaque的效果,請使用“ Transparent

暫無
暫無

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

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