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

Coq 如何使用重写策略指定位置?,coq,coq-tactic,Coq,Coq Tactic,我有一个简单的列表引理,上面写着n::l=[n]++l,其证明如下 Lemma cons_to_app : (forall (n: nat) (l: list nat), n :: l = [n] ++ l). Proof. simpl. reflexivity. Qed. 现在我想用这个校对重写cons术语:,无论它们出现在校对目标中的什么地方。例如,考虑以下内容: Lemma easy_lemma : forall (n : nat) (xs ys : list nat), (n::

我有一个简单的列表引理,上面写着
n::l=[n]++l
,其证明如下

Lemma cons_to_app : (forall (n: nat) (l: list nat),  n :: l = [n] ++ l).
Proof.
  simpl. reflexivity.
Qed.
现在我想用这个校对重写cons术语
,无论它们出现在校对目标中的什么地方。例如,考虑以下内容:

Lemma easy_lemma : forall (n : nat) (xs ys : list nat), (n::xs) ++ (n::ys) = (n::xs) ++ ([n] ++ ys).
我想把
(n::ys)
重写成
[n]++ys
,证明就完成了。由于
n::ys
是第二次在证明目标中出现
::
,我原以为
在2
处将const_重写为应用程序会起作用,但实际上它在第三次
::
时起作用,并将证明目标更改为
(n::xs)++n::ys=([n]++xs+[n]++ys


我可以指定什么位置使重写在
(n::ys)
术语上工作?

我仍然找不到在
上谈论
重写的确切行为的原始源代码(除了)。链接上的帖子写于2011年,但在Coq版本8.9.1中似乎到2019年仍然有效,并且可能不会被“修复”,因为该问题以“无效”结束,称为“更改行为将破坏向后兼容性”


问题
在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.
始终选择子项
n::xs
,然后将第n次出现的
n::xs
重写为
[n]++xs
。第二个
n::xs
恰好是第三个
。:。

解决方案 简单的解决方法是给出足够的参数来告诉Coq要重写的确切内容<代码>重写(cons_to_app_ys)
在这种情况下就足够了

另一种选择是使用
setoid\u rewrite
策略,它查看所有适用的子项。然而,它有时看起来过于深入的定义,确实是这个例子的情况<代码>setoid\u将cons\u重写为应用程序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
折叠
应用程序
会得到
[n]++(xs++n::ys)
,这与我们想要的不同,即
([n]++xs)++n::ys
。我们可以观察到,
setoid\u rewrite
app
展开一次,将LHS更改为
n:(xs++n::ys)
,然后实例化引理来重写最外层的
:。


为了避免展开
app
,我们可以在重写之前声明
不透明app.
。然后
setoid\u重写。。。at 1给出了我们想要的(at 2也一样)。要恢复
不透明的效果
,请使用
透明

我仍然找不到在
处谈论
重写的确切行为的原始源代码(除了)。链接上的帖子写于2011年,但在Coq版本8.9.1中似乎到2019年仍然有效,并且可能不会被“修复”,因为该问题以“无效”结束,称为“更改行为将破坏向后兼容性”


问题
在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.
始终选择子项
n::xs
,然后将第n次出现的
n::xs
重写为
[n]++xs
。第二个
n::xs
恰好是第三个
。:。

解决方案 简单的解决方法是给出足够的参数来告诉Coq要重写的确切内容<代码>重写(cons_to_app_ys)
在这种情况下就足够了

另一种选择是使用
setoid\u rewrite
策略,它查看所有适用的子项。然而,它有时看起来过于深入的定义,确实是这个例子的情况<代码>setoid\u将cons\u重写为应用程序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
折叠
应用程序
会得到
[n]++(xs++n::ys)
,这与我们想要的不同,即
([n]++xs)++n::ys
。我们可以观察到,
setoid\u rewrite
app
展开一次,将LHS更改为
n:(xs++n::ys)
,然后实例化引理来重写最外层的
:。


为了避免展开
app
,我们可以在重写之前声明
不透明app.
。然后
setoid\u重写。。。at 1给出了我们想要的(at 2也一样)。要恢复
不透明的效果,请使用
透明的

我想我在某处读到,
在n处重写引理
使用第一次出现(
(n::xs)
,在这种情况下)实例化等式,然后重写它的第n次出现(第2次
(n::xs)
恰好是第3次
。:
)。因此,在n
没有将cons\u重写为将重写
(n::ys)
的应用程序。你至少需要
重写(cons\u to\u app\uys)
。哦,这很有趣。我正在看战术文档,
rewrite at
的条目指的是
pattern at
,它说“β-展开只考虑项的出现次数num+。出现次数从左到右。”你记得你在哪里读到你说的吗@马克·布布勒的解释是正确的,但我也不记得我在哪里见过它。@马克这是我发现的最好的:。我想我在某处读到,
在n处重写引理
使用第一次出现(
(n::xs)
,在这种情况下)实例化等式,然后重写它的第n次出现(
(n::xs)的第2次)
正好是第三个
。:。
)。因此,在n
没有将cons\u重写为将重写
(n::ys)
的应用程序。你至少需要
重写(cons\u to\u app\uys)
。哦,这很有趣。我正在查看战术文档和
rewrite的条目