关于列表和转速的引理(列表)

时间:2019-07-02 22:56:33

标签: coq

试图证明以下问题,我陷入了困境。关于列表的通常定理已通过归纳证明,但我不知道接下来要去哪里。

Lemma reverse_append : forall (T : Type) (h : T) (t : list T), h::t = rev(t) ++ [h] -> t = rev(t).
Proof.
  intros. induction t.
  - simpl. reflexivity.
  - simpl. simpl in H.

Result:

1 subgoal (ID 522)

T : Type
h, x : T
t : list T
H : h :: x :: t = (rev t ++ [x]) ++ [h]
IHt : h :: t = rev t ++ [h] -> t = rev t
============================
x :: t = rev t ++ [x]

2 个答案:

答案 0 :(得分:2)

主要答案

在开始证明定理之前,您应该尝试彻底了解定理的内容。你的定理就是错误的。

反例:2 :: [1;2] = rev [1;2] ++ [2],但是[1;2]不是回文。

充分证明:

Require Import List.
Import ListNotations.

Lemma reverse_append_false :
  ~(forall (T : Type) (h : T) (t : list T), h::t = rev(t) ++ [h] -> t = rev(t)).
Proof. intros H. specialize (H nat 2 [1;2] eq_refl). inversion H. Qed.

小问题

rev(t)应该只是rev t。只是一个审美观点,但您可能应该使自己更加熟悉以函数式编程风格进行编写。

  

通常使用归纳法证明列表的定理

这是一个非常幼稚的声明,尽管在技术上是正确的。对价值进行归纳的方法有很多,选择最有效的归纳是一项关键技能。仅举几例:

  • 列表上的归纳
  • 列表的长度上的归纳
    • 在处理rev和其他保留长度的函数时,它会非常频繁地出现
    • Example
  • 如果简单归纳无效,请考虑自定义归纳方案

答案 1 :(得分:1)

引理不是正确的。在证明任何东西之前,您应该确保它有意义。该假设实质上是说h::t = rev (h::t)。但是,为什么这意味着t = rev t?如果您从回文列表的开头删除元素,则它可能不再成为回文。例如,神化是回文('deified'= rev'deified'),但神化不是回文。

在这种特殊情况下,示例1::[2; 1] = (rev [2; 1]) ++ [1],因为两者都是[1; 2; 1]。但是[2; 1]不等于rev [2; 1] = [1; 2]