[英]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.