Require Import FMapAVL.
Require Import OrderedTypeEx.
Module M := FMapAVL.Make(Nat_as_OT).
Fixpoint cc (n: nat) (c: M.t nat):bool :=
match M.find n c with
| None => false
| Some e => true
end.
Lemma l: forall (n: nat) (k:nat) (m: M.t nat), cc n m = true -> cc n (M.add k k m) = true.
Proof.
intros.
inversion H.
调用inversion H
之前的环境:
1 subgoals
n : nat
k : nat
m : M.t nat
H : cc n m = true
______________________________________(1/1)
cc n (M.add k k m) = true
基于我对反演策略的理解,使用策略inversion H
,应该能够预测M.find n m = Some e
。但它只是重复H.
有人可以帮我解释Coq如何解释这里的事情吗?
答案 0 :(得分:1)
当假设的主谓词是归纳谓词时,反转就起作用了。这里假设H
的主谓词是一个平等,并且它发生在内部平等的深层由归纳谓词表示。所以inversion
认为它可以发挥作用。
直观地,inversion
试图帮助您推断可以使用什么构造函数,并且通过添加与使用此构造函数来证明必须满足的约束相对应的相等语句来进行此推理。假设
在您的情况下,相等性由仅具有一个构造函数的归纳定义表示。所以inversion
看看使用这个构造函数的约束是什么:相等的两个成员应该是相同的。所以inversion
增加了一个新的平等,表明平等的两个方面应该是相同的。这就是为什么你看到这个假设的重复。
恰好inversion
不适合在这里使用。
在之前对your questions之一的回答中,我写道你不应该使用Fixpoint
来定义函数cc
,因为这个函数不是递归的。请按照我的建议写下
Definition cc (n: nat) (c: M.t nat):bool :=
match M.find n c with
| None => false
| Some e => true
end.
这将使其余的校样更容易(我们也可以使用cc
定义Fixpoint
来解决您的问题,但这会增加不必要的复杂性)。我对你的问题的回答现在假设你确实遵循了这一点
一点建议。以下是如何推进您的证明。
Proof.
intros n k m H; unfold cc in H.
此时,您的假设H
包含模式匹配语句与true
之间的相等性。你想要的是通过在你的证明中执行相同的案例分析来研究这个匹配语句的两种可能的计算。这是怎么做的。
case_eq (M.find n m); [intros v Hfind | intros Hfind].
在此之后,你将有两个目标。一个有H : match ... with ... end = true
和Hfind : M.find n m = Some v
,另一个有H : match M.find n m with ... end = true
和Hfind : M.find n m = None
。使用Hfind
重写H
,您可以将假设更改为H : false = true
,这可以使用discriminate
解决。请记住这一点。
对于第一个目标,您应该可以通过unfold cc
再次进步。
现在M.find n (M.add k k m)
的价值是多少?如果n
为k
,则此值为Some k
。如果n
与k
不同,则M.find n (M.add k k m)
的值与M.find n m
的值相同。我们已经为此值指定了名称,此名称为v
,假设Hfind
表示如此。
要生成关于n
是否等于k
的案例分析,建议您撰写destruct (M.E.eq_dec k n) as [kn | knn]
。
所以你将有一个假设kn : k = n
的第一个目标。在这种情况下,我建议您通过键入以下命令来证明中间事实。
assert (step : M.find n (M.add k k m) = Some k).
您应该可以使用M.find_1
,M.add_1
来证明这一点。
完成此校对后,请使用step
重写,然后结束。
然后你将有一个假设knn : k <> n
的第二个目标,对于这个你必须证明一个不同的中间陈述,你再次使用M.find_1
来证明,然后你使用M.add_2
}和M.find_2
。