Coq 使用';展开';在归纳的递归步骤内的不动点

Coq 使用';展开';在归纳的递归步骤内的不动点,coq,coq-tactic,Coq,Coq Tactic,我试图在coq中证明一些东西,同样的问题不断出现; 我想在归纳的递归(不是零)步骤中展开不动点的定义。“展开”按预期工作,下面是一个示例: 展开列表反转(rev)定义之前: n : nat l' : natlist IHl' : rev (rev l') = l' ============================ rev (rev (n :: l')) = n :: l' 之后: n : nat l' : natlist IHl' : rev (rev

我试图在coq中证明一些东西,同样的问题不断出现; 我想在归纳的递归(不是零)步骤中展开不动点的定义。“展开”按预期工作,下面是一个示例:

展开列表反转(rev)定义之前:

  n : nat
  l' : natlist
  IHl' : rev (rev l') = l'
  ============================
  rev (rev (n :: l')) = n :: l'
之后:

  n : nat
  l' : natlist
  IHl' : rev (rev l') = l'
  ============================
  (fix rev (l : natlist) : natlist := match l with
                                      | [ ] => [ ]
                                      | h :: t => rev t ++ [h]
                                      end)
    ((fix rev (l : natlist) : natlist := match l with
                                         | [ ] => [ ]
                                         | h :: t => rev t ++ [h]
                                         end) l' ++ [n]) = n :: l'
到目前为止还不错。现在,我希望
siml
能够找出我在归纳法的非零情况下,因为
n::l'
永远不可能是零, 并简化匹配的nil情况(
[]=>[]
),只保留定义中的非nil部分

不幸的是,它并没有隐式地做到这一点。如何使递归不动点定义的
展开
与归纳很好地结合起来?如何获得:

  n : nat
  l' : natlist
  IHl' : rev (rev l') = l'
  ============================
  rev (rev l' ++ [n]) = n :: l'
根据内部
rev
rev
定义

注意:列表的使用与此无关,相同的技术可用于任何归纳定义的类型

编辑:导致After状态的版本和证明的定义


您的
After:
基本上是
rev(rev l'+[n])
(展开
rev
),这意味着您希望看到发生的减少已经发生。现在你可能想证明一个类似于
rev(xs++ys)=revys++revxs的辅助引理,请提交一个。当我们可以一步一步地通过证明并尝试不同的事情时,回答起来就容易多了。添加了
rev
的定义以及导致After状态的证明。当然,我已经证明了这一点,但这个证明被用作示例。我真正想要的是减少从
rev
定义中展开的讨厌的
match
,因为模式匹配的nil情况是不可能的。如果我为所有n:nat,l:natlist,n::l~=[]
证明
,那该怎么办?但是从
cons
的定义来看,这应该是显而易见的。正如我所说:它已经被简化了。如果您尝试
fold rev
,您将看到它现在已减少到
rev(rev l'+[n])
。是的!折叠是我想要的!这是超级反直觉的顺便说一句,证明的关键是
open rev。折叠版本,读起来好像什么都没做。比如说,为什么这不是默认情况下
siml
尝试的第一个策略之一呢?
siml
取而代之的是
unfold rev;fold rev
在我的机器上确实适用于。我深入研究了一下,似乎有一个很好的理由表明Coq不允许对递归匹配定义求值,即使输入将明显匹配非nil分支。在我的示例中,
n::l'
永远不能是
nil
,但是如果在哪里计算匹配并去掉
nil
分支,递归就没有退出条件,可能会导致无限循环。
Fixpoint rev (l:natlist) : natlist :=
  match l with
  | nil    => nil
  | h :: t => rev t ++ [h]
  end.

Theorem rev_involutive : forall l : natlist,
  rev (rev l) = l.
Proof.
  intros l. induction l as [| n l'].
  - reflexivity.
  - unfold rev.