coq - 无法证明非标准递归函数的微不足道的引理
问题描述
我很难证明关于我定义的函数的非常简单的引理。这是我的定义:
Require Import List.
Require Export Omega.
Require Export FunInd.
Require Export Recdef.
Notation "A :: B" := (cons A B).
Notation "[]" := nil.
Notation "[[ A ]]" := (A :: nil).
Inductive tm :=
| E: nat -> tm
| L: list tm -> tm.
Definition T := list tm.
Fixpoint add_list (l: list nat) : nat :=
match l with
| [] => 0
| n :: l' => n + (add_list l')
end.
Fixpoint depth (t: tm) : nat :=
match t with
| E _ => 1
| L l => 1 + (add_list (map depth l))
end.
Definition sum_depth (l: T) := add_list (map depth l).
Function sum_total (l: T) {measure sum_depth l} : nat :=
match l with
| [] => 0
| [[E n]] => n
| [[L li]] => sum_total li
| E n :: l' => n + (sum_total l')
| L li :: l' => (sum_total li) + (sum_total l')
end.
Proof.
- auto.
- intros; unfold sum_depth; subst. simpl; omega.
- intros; subst; unfold sum_depth; simpl; omega.
- intros; subst; unfold sum_depth; simpl; omega.
Defined.
无法更改感应类型。
我可以证明简单的命题,比如Lemma test : forall n, sum_total [[E n]] = n.
使用计算策略,但另一个微不足道的引理,比如Lemma test2 : forall l, sum_total [[L l]] = sum_total l.
挂起。
解决方案
首先,策略“挂”在您提到的目标上似乎是可以的compute
(因为在使用Function … Proof. … Defined.
定义方法时,您的函数sum_total
包含一些不打算计算的证明术语 - 尤其是在任意参数上l
;也许是一种策略例如simpl
或cbn
更适合这种情况)。
独立于我对 list notations 的评论,我仔细研究了您的形式化,Function
在您的情况下似乎不需要该命令,因为sum_total
本质上是结构性的,因此您可以使用 mere Fixpoint
,前提是您正在查看的归纳类型稍微改写一次性定义为相互定义的归纳类型(请参阅Coq 的 refman 中 Inductive 命令的相应文档,其中给出了“树/森林”的类似典型示例)。
为了详细说明您的示例,您可能需要像这样调整您的定义(如果可能适用于您的用例):
Inductive tm :=
| E: nat -> tm
| L: T -> tm
with T :=
Nil : T
| Cons : forall (e : tm) (l : T), T.
Notation "[[ A ]]" := (Cons A Nil).
Fixpoint sum_total (l: T) {struct l} : nat :=
match l with
| Nil => 0
| [[E n]] => n
| [[L li]] => sum_total li
| Cons (E n) l' => n + (sum_total l')
| Cons (L li) l' => (sum_total li) + (sum_total l')
end.
(* and the lemma you were talking about is immediate *)
Lemma test2 : forall l, sum_total [[L l]] = sum_total l.
reflexivity.
Qed.
否则(如果你不能tm
像这样改写你的归纳),另一种解决方案是使用另一种策略而不是Function
定义你的sum_total
函数,例如Program Fixpoint
,或Equations
插件(这比Function
处理非结构递归/依赖时更灵活和健壮-键入的模式匹配)。
编辑:由于 OP 提到归纳类型本身不能改变,所以有一个直接的解决方案,即使只使用Function
机械:依靠定义自动生成的“方程引理”。
更准确地说,如果您按原样使用脚本,那么您将“免费”获得以下引理:
Search sum_total "equation".
(*
sum_total_equation:
forall l : T,
sum_total l =
match l with
| [] => 0
| [[E n]] => n
| E n :: (_ :: _) as l' => n + sum_total l'
| [[L li]] => sum_total li
| L li :: (_ :: _) as l' => sum_total li + sum_total l'
end
*)
因此,您可以通过以下方式轻松陈述和证明您感兴趣的引理:
Lemma test2 : forall l, sum_total [[L l]] = sum_total l.
intros l.
rewrite sum_total_equation.
reflexivity.
Qed.
推荐阅读
- .net - 问:如何配置 cloudbuild.yaml 来运行测试?
- mysql - 如果输入为空,如何忽略枚举类型?
- php - 非法字符串偏移“名称”和未初始化的字符串偏移:0
- java - 如何从 StepExecutionListener 中的 beforeStep 方法中跳过步骤执行?
- c++ - 将基类的子类中的公共方法私有化
- c# - 服务远程处理/发送者 - 接收者
- ios - MessageKit 为 didSelectURL 设置 MessageLabelDelegate
- javascript - 浏览器如何解码这些混淆的类名?
- java - Selenium 无法通过 webdrive 避免检测
- python - PIL ImageDraw 文本颜色变为蓝色