如何在 Coq 的简化过程中应用一次函数?
How to apply a function once during simplification in Coq?
据我了解,Coq 中的函数调用是不透明的。
有时,我需要使用 unfold
来应用它,然后 fold
将函数 definition/body 变回它的名字。这通常很乏味。我的问题是,是否有更简单的方法让应用函数调用的特定实例?
作为一个最小的例子,对于列表 l
,证明右追加 []
不会改变 l
:
Theorem nil_right_app: forall {Y} (l: list Y), l ++ [] = l.
Proof.
induction l.
reflexivity.
剩下:
1 subgoals
Y : Type
x : Y
l : list Y
IHl : l ++ [] = l
______________________________________(1/1)
(x :: l) ++ [] = x :: l
现在,我需要应用 ++
的定义(即 app
)一次(假设目标中还有其他 ++
我不想 apply/expand).目前,我知道实现这个一次性应用程序的唯一方法是先展开 ++
然后折叠它:
unfold app at 1. fold (app l []).
给予:
______________________________________(1/1)
x :: l ++ [] = x :: l
但这很不方便,因为我必须弄清楚要在 fold
中使用的术语的形式。我做了计算,而不是 Coq。我的问题归结为:
有没有更简单的方法实现这个一次性函数应用达到同样的效果?
如果你想让 Coq 为你执行一些计算,你可以使用 simpl
、compute
或 vm_compute
。如果函数的定义是Opaque
,上面的解法会失败,但是你可以先证明一个重写引理如:
forall (A:Type) (a:A) (l1 l2: list A), (a :: l1) ++ l2 = a :: (l1 ++ l2).
使用您的技术,然后在必要时rewrite
使用它。
这是一个使用 simpl
的例子:
Theorem nil_right_app: forall {Y} (l: list Y), l ++ nil = l.
Proof.
(* solve the first case directly *)
intros Y; induction l as [ | hd tl hi]; [reflexivity | ].
simpl app. (* or simply "simpl." *)
rewrite hi.
reflexivity.
Qed.
为了回答您的评论,我不知道如何告诉 cbv
或 compute
只计算某个符号。请注意,在您的情况下,它们似乎过于急切地计算并且 simpl
效果更好。
据我了解,Coq 中的函数调用是不透明的。
有时,我需要使用 unfold
来应用它,然后 fold
将函数 definition/body 变回它的名字。这通常很乏味。我的问题是,是否有更简单的方法让应用函数调用的特定实例?
作为一个最小的例子,对于列表 l
,证明右追加 []
不会改变 l
:
Theorem nil_right_app: forall {Y} (l: list Y), l ++ [] = l.
Proof.
induction l.
reflexivity.
剩下:
1 subgoals
Y : Type
x : Y
l : list Y
IHl : l ++ [] = l
______________________________________(1/1)
(x :: l) ++ [] = x :: l
现在,我需要应用 ++
的定义(即 app
)一次(假设目标中还有其他 ++
我不想 apply/expand).目前,我知道实现这个一次性应用程序的唯一方法是先展开 ++
然后折叠它:
unfold app at 1. fold (app l []).
给予:
______________________________________(1/1)
x :: l ++ [] = x :: l
但这很不方便,因为我必须弄清楚要在 fold
中使用的术语的形式。我做了计算,而不是 Coq。我的问题归结为:
有没有更简单的方法实现这个一次性函数应用达到同样的效果?
如果你想让 Coq 为你执行一些计算,你可以使用 simpl
、compute
或 vm_compute
。如果函数的定义是Opaque
,上面的解法会失败,但是你可以先证明一个重写引理如:
forall (A:Type) (a:A) (l1 l2: list A), (a :: l1) ++ l2 = a :: (l1 ++ l2).
使用您的技术,然后在必要时rewrite
使用它。
这是一个使用 simpl
的例子:
Theorem nil_right_app: forall {Y} (l: list Y), l ++ nil = l.
Proof.
(* solve the first case directly *)
intros Y; induction l as [ | hd tl hi]; [reflexivity | ].
simpl app. (* or simply "simpl." *)
rewrite hi.
reflexivity.
Qed.
为了回答您的评论,我不知道如何告诉 cbv
或 compute
只计算某个符号。请注意,在您的情况下,它们似乎过于急切地计算并且 simpl
效果更好。