在Coq记录成员的归纳?

时间:2018-02-17 10:36:57

标签: coq coq-tactic

考虑一个简单的记录成员归纳示例:

Record Foo : Type := mkFoo { foo: nat }.

Definition double (f: Foo) : Foo :=
  mkFoo (2 * foo f)%nat.


Theorem double_doubles: forall (f: Foo),
    foo (double f) = (2 * foo f)%nat.
Proof.
  intros.
  induction (foo f).
  (* How do I prevent this loss of information? *)
  (* stuck? *)
Abort.


Theorem double_doubles: forall (f: Foo),
    foo (double f) = (2 * foo f)%nat.
Proof.
  intros.
  destruct f.
  (* destruct is horrible if your record is large / contains many things *)
  induction foo0.
  simpl. auto.
  intros. simpl. auto.
Qed.

induction (foo f),我陷入了目标 foo (double f) = 2 * 0

我以某种方式丢失了我在foo f上执行归纳的信息(我没有假设foo f = 0

然而,destruct f并不令人满意,因为我有大约5个成员记录在扩展时在假设部分看起来非常难看。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

您可以使用remember策略为表达式命名,从而产生一个可以归纳分析的变量。该策略生成一个将变量与记忆表达式相关联的等式,使您可以跟踪所需的信息。

为了说明,请考虑以下证明脚本。

Record Foo : Type := mkFoo { foo: nat }.

Definition double (f: Foo) : Foo :=
  mkFoo (2 * foo f)%nat.

Theorem double_doubles: forall (f: Foo),
    foo (double f) = (2 * foo f)%nat.
Proof.
  intros.
  remember (foo f) as n eqn:E.
  revert f E.
  induction n.

致电remember后,目标变为:

  f : Foo
  n : nat
  E : n = foo f
  ============================
  foo (double f) = 2 * n

如果您在n之后直接在remember上进行归纳,则您可能无法完成校对,因为您将获得的归纳假设不够通用。如果遇到此问题,可能需要概括定义n的表达式中出现的一些变量。在上面的脚本中,调用revert f EfE放回目标中,从而解决了这个问题。