我是 coq 的初学者。
我不知道 intros [=]
和 intros [= <- H]
的含义。我找不到一个简单的解释。有人可以向我解释一下这两个吗?
问候
答案 0 :(得分:2)
相关文档为 here。我会添加一点解释说明。
介绍模式的第一个历史用途是动态分解包含在归纳对象中的数据。这是第一个简单的例子(用 coq 8.13.2 测试)。
Lemma forall A B, A /\ B -> B /\ A.
Proof.
如果您运行策略 intros A B H
,那么假设 H
将是 A /\ B
的证明。从道德上讲,这包含 A
持有的知识,但不能这样使用,因为它是对更强事实的证明。通常情况下,用户想要直接分解这个假设,这通常通过键入 destruct H as [Ha Hb]
来完成。但是如果你马上知道你不会保留假设 H
,为什么不找一个更短的表达式。这就是介绍模式的用途。
因此,您键入以下命令并获得结果目标:
Intros A B [Ha Hb].
(* resulting goal
A, B : Prop
Ha : A
Hb : B
============================
B /\ A
*)
Abort.
我不会完成这个证明。但是您会了解介绍模式的用途:当归纳类型(如这里的连词)将多条信息打包在一起时,即时分解信息。
现在,平等信息也可以将几条信息打包在一起。假设现在我们正在处理自然数列表,并且我们有以下等式。
Require Import List.
Lemma intro_pattern_example2 n m p q l1 l2 :
(n :: S m :: l1) = (p :: S q :: l2) -> q :: p :: l2 = m :: n :: l1.
蕴涵左侧的相等是两个列表之间的相等,但它实际上包含了几个更基本的信息:n = p
、m = q
和 l1 = l2
.如果你只输入 intros H
,你会得到两个长度为 3 的列表之间的相等性,但是如果你输入 intros [=]
,你要求证明系统探索每个相等成员的结构并检查构造函数何时出现较小的信息可以放在单独的假设而不是大的假设中。这是使用 injection
策略的简写。这是示例。
intros [= Hn Hm Hl1].
(*resulting goal:
n, m, p, q : nat
l1, l2 : list nat
Hn : n = p
Hm : m = q
Hl1 : l1 = l2
============================
q :: p :: l2 = m :: n :: l1
*)
所以你看,这个介绍模式解包了信息,否则这些信息会被困在一个更复杂的假设中。
现在,当假设是等式时,您可能希望立即执行另一个操作。你可能想用它重写。在介绍模式中,这是通过用箭头替换您赋予该等式的名称来完成的。让我们在之前的目标上测试一下。
Undo.
intros [= -> -> ->].
(* resulting goal
p, q : nat
l2 : list nat
============================
q :: p :: l2 = q :: p :: l2
*)
现在这个目标可以通过 reflexivity
、trivial
或 auto
快速解决。请注意,假设用于重写,但它们并未保留在目标上下文中,因此必须谨慎使用这种直接从介绍模式重写的可能性,因为您实际上丢失了一些信息。
[= ]
介绍模式特别用于相等和两个成员都是数据类型构造函数时。它利用了这些构造函数的自然注入特性。数据类型构造函数尊重另一个属性。事实上,具有不同头部构造函数的两条数据永远不可能相等。这在 Coq 中被 discriminate
策略利用。 [=]
介绍模式是 injection
和 discriminate
策略的简写。