Lemma rev_firstn : forall (x : list bool) (n : nat),
rev (firstn n x) = firstn n (rev x).
我花了很多时间。我从一个明智的目标开始,但总是以一个无法证明的目标结束。
这是我目前的做法:
Proof.
intros. generalize dependent x. induction n.
+ easy.
+ induction x.
- easy.
-
就我而言,我现在有:
IHn : forall x : list bool, rev (firstn n x) = firstn n (rev x)
IHx : rev (firstn (S n) x) = firstn (S n) (rev x)
我的目标是:
rev (firstn (S n) (a :: x)) = firstn (S n) (rev (a :: x))
有没有一种方法可以在IHx中将x泛化,所以我可以将其专门化为 (a :: x)?由于我不知道执行此操作的正确策略,因此请尝试以下操作,最后得出前面提到的不可能的目标。
Proof.
intros. generalize dependent x. induction n.
+ easy.
+ induction x.
- easy.
- assert (rev_cons : forall (b : bool) (l : list bool),
rev (b :: l) = rev l ++ [b]).
{ easy. } rewrite firstn_cons.
rewrite rev_cons. rewrite rev_cons. specialize (@IHn x).
rewrite IHn.
Goal: firstn n (rev x) ++ [a] = firstn (S n) (rev x ++ [a])
该目标是不可能的,因为对于n = 0且rev x = h :: t,该目标
减少为[a] = List.hd (rev (h :: t)) ++ [a]
。
这个引理实际上是不合理的,还是我只是缺少一些战术?
答案 0 :(得分:3)
假设firstn
和rev
是我所认为的,我不认为引理是正确的。
rev (firstn 2 [true, false, false])
= rev [true, false]
= [false, true]
但是
firstn 2 (rev [true, false, false])
= firstn 2 [false, false, true]
= [false, false]
本质上,rev (firstn n x)
是n
的前x
个元素(以相反的顺序),但是firstn n (rev x)
是{{1 }}(也可以相反的顺序)。为了使这种引理在任何形式的普遍性上都成立,您将需要x最多具有n
个元素。正如Arthur Azevedo De Amorim在评论中指出的那样,如果您插入x
只看{{1}的最后n
(最多)个元素,那么您也可以获得正确的引理版本。 }。
skipn n