在Coq中给出一个任意的归纳命题定义,是否有一个通用的公式来推导出一个合理的disj_conj_intro_pattern,以便在归纳命题上调用感应策略时使用?
通常,任何一个归纳定义构造函数的完整intro_pattern可能需要(名称)多个假设和多个归纳假设,在这种情况下,模式中提供的名称顺序可以包括所有参数,然后是一个假设和相应的归纳假设,接着是一个或多个由假设和归纳假设组成的附加对。例如,Software Foundations包括以下内容:
Inductive exp_match {T} : list T -> reg_exp T -> Prop :=
| MEmpty : exp_match [] EmptyStr
| MChar : forall x, exp_match [x] (Char x)
| MApp : forall s1 re1 s2 re2,
exp_match s1 re1 ->
exp_match s2 re2 ->
exp_match (s1 ++ s2) (App re1 re2)
| MUnionL : forall s1 re1 re2,
exp_match s1 re1 ->
exp_match s1 (Union re1 re2)
| MUnionR : forall re1 s2 re2,
exp_match s2 re2 ->
exp_match s2 (Union re1 re2)
| MStar0 : forall re, exp_match [] (Star re)
| MStarApp : forall s1 s2 re,
exp_match s1 re ->
exp_match s2 (Star re) ->
exp_match (s1 ++ s2) (Star re).
Notation "s =~ re" := (exp_match s re) (at level 80).
Theorem in_re_match : forall T (s : list T) (re : reg_exp T) (x : T),
s =~ re ->
In x s ->
In x (re_chars re).
Proof.
intros T s re x Hmatch Hin.
induction Hmatch
as [
|x'
|s1 re1 s2 re2 Hmatch1 IH1 Hmatch2 IH2
|s1 re1 re2 Hmatch IH|re1 s2 re2 Hmatch IH
|re|s1 s2 re Hmatch1 IH1 Hmatch2 IH2].
在这个例子中,MApp和MStarApp的intro_patterns每个都有两对假设和归纳假设 - 大概是因为这两个构造函数都包含一个表达式
x - > y - > ž
关于这一点,目前的参考手册似乎只是说
诱导期限为disj_conj_intro_pattern
这表现为归纳术语,但使用的是名称 disj_conj_intro_pattern命名引入的变量 上下文。 disj_conj_intro_pattern通常必须采用[ p11 ... p1n1 | ...... | pm1 ... pmnm],m是构造函数的数量 这个词的类型。每个变量都是通过感应引入的 第i个目标的上下文从列表pi1 ... pini中获取其名称 订购。如果没有足够的名称,感应就会发明名称 要引入的剩余变量。更一般地说,pij可以是任何 析取/连接引入模式(参见第8.3.2节)。对于 例如,对于具有一个构造函数的归纳类型,模式 可以使用符号(p1,...,pn)代替[p1 ... pn]。
这似乎没有说明如何为给定的归纳定义确定完整的disj_conj_intro_pattern的正确形式。
我的上述经验观察是:1)每个构造函数的形式参数首先出现,然后是构造函数的假设与相应的归纳假设相结合; 2)假设和归纳假设对的数量来自构造函数中假设的数量,即事物的总和?或者还有它吗?
除了参考手册的战术章节以及第1章中关于Gallina语法模式的一般性讨论外,还有其他相关文件吗?
答案 0 :(得分:0)
如果我理解你的问题,那么答案就是'是'。您可以导出入门的介绍模式。
Coq自动为任何归纳定义生成归纳原则,并将其添加_ind
作为后缀,因此exp_match
的归纳原则变为exp_match_ind
。如果您使用exp_match_ind
命令探索Check
的类型,则可以生成所需的介绍模式。
Check exp_match_ind.
(* output:
exp_match_ind
: forall (T : Type) (P : list T -> reg_exp T -> Prop),
P [] EmptyStr ->
(forall x : T, P [x] (Char x)) ->
(forall (s1 : list T) (re1 : reg_exp T)
(s2 : list T) (re2 : reg_exp T),
s1 =~ re1 ->
P s1 re1 ->
s2 =~ re2 -> P s2 re2 -> P (s1 ++ s2) (App re1 re2)) ->
(forall (s1 : list T) (re1 re2 : reg_exp T),
s1 =~ re1 -> P s1 re1 -> P s1 (Union re1 re2)) ->
(forall (re1 : reg_exp T) (s2 : list T) (re2 : reg_exp T),
s2 =~ re2 -> P s2 re2 -> P s2 (Union re1 re2)) ->
(forall re : reg_exp T, P [] (Star re)) ->
(forall (s1 s2 : list T) (re : reg_exp T),
s1 =~ re ->
P s1 re ->
s2 =~ Star re -> P s2 (Star re) -> P (s1 ++ s2) (Star re)) ->
forall (l : list T) (r : reg_exp T), l =~ r ->
P l r
*)
这种类型表示(如果你跳过最初的forall
“标题”)你需要证明一堆子目标来证明目标P l r
。顶级的每个->
都会分隔子目标:
1)MEmpty
案例:
P [] EmptyStr
没有假设,这就是我们开始的原因
induction Hmatch as [ |
- 请注意|
左侧没有任何内容。
2)MChar
案例:
(forall x : T, P [x] (Char x))
这种情况下的介绍模式很简单:对于某些x'
,我们需要证明P [x'] (Char x')
。此时我们的模式变为:[ | x'
...
3)MApp
案例:
(forall (s1 : list T) (re1 : reg_exp T)
(s2 : list T) (re2 : reg_exp T), (* s1 re1 s2 re2 *)
s1 =~ re1 -> (* Hmatch1 *)
P s1 re1 -> (* IH1 *)
s2 =~ re2 -> (* Hmatch2 *)
P s2 re2 -> (* IH2 *)
P (s1 ++ s2) (App re1 re2)) (* the current subgoal *)
我根据定理in_re_match
中使用的标记在上面的注释中标记了变量和假设。此时我们的模式变为:[ | x' | s1 re1 s2 re2 Hmatch1 IH1 Hmatch2 IH2
...
其余的子目标可以类似地完成,从而产生定理中使用的模式。