coq - 如何使用递减参数进行递归调用?
问题描述
Inductive bar {X : Type} : list X -> Prop :=
| bar_nil : bar []
| bar_fst : forall x l, bar (rev l ++ l) -> bar (rev l ++ [x] ++ l)
| bar_snd : forall x l, bar (rev l ++ [x] ++ l) -> bar (rev l ++ [x; x] ++ l).
Axiom bar_surround :
forall X x (l : list X),
bar l -> bar ([x] ++ l ++ [x]).
Inductive list_last {X : Type} : list X -> Prop :=
| ll_nil : list_last []
| ll_snoc : forall l x, list_last l -> list_last (l ++ [x]).
Axiom ll_app :
forall X (a b : list X),
list_last a -> list_last b -> list_last (a ++ b).
Axiom ll_from_list :
forall {X} (l : list X),
list_last l.
Axiom app_head_eq :
forall X (a b c : list X),
a ++ c = b ++ c -> a = b.
Theorem foo :
forall X (l: list X), l = rev l -> bar l.
Proof.
intros.
induction l.
- constructor.
- assert (Hll := ll_from_list l).
inversion Hll.
+ apply (bar_fst x []). apply bar_nil.
+ rewrite <- H1 in H.
simpl in H.
rewrite rev_app_distr in H.
rewrite <- app_assoc in H.
simpl in H.
inversion H.
apply app_head_eq in H4.
apply bar_surround.
1 subgoal
X : Type
x : X
l, l0 : list X
x0 : X
H : x :: l0 ++ [x0] = x0 :: rev l0 ++ [x]
IHl : l = rev l -> bar l
Hll : list_last l
H0 : list_last l0
H1 : l0 ++ [x0] = l
H3 : x = x0
H4 : l0 = rev l0
______________________________________(1/1)
bar l0
我离解决这个练习只有一步之遥,但我不知道如何做归纳步骤。请注意,这IHl
在这里没有用,并且用 Induction on 替换 Induction l
onHll
也会有类似的问题。在这两种情况下,归纳假设都会期望一个减少一步的调用,而我需要两个 - 一个从等式两侧的列表的开头和结尾获取项目。
考虑一下我要证明的函数的类型是forall X (l: list X), l = rev l -> bar l
并且我l0 = rev l0 -> bar l0
的目标是在这里。l0
是一个减少的参数,从而使递归调用安全。
我应该在这里做什么?
解决方案
您可以证明以下归纳谓词:
Inductive delist {A : Type} : list A -> Prop :=
| delist_nil : delist []
| delist_one x : delist [x]
| delist_cons x y l : delist l -> delist (x :: l ++ [y])
.
Theorem all_delist {A} : forall xs : list A, delist xs.
然后在你的最终定理中,归纳delist xs
将分成你需要的情况。
另一种解决方案是对列表长度进行强归纳:
Lemma foo_len X : forall (n : nat) (l: list X), length l <= n -> l = rev l -> bar l.
Proof.
induction n.
(* Nat.le_succ_r from the Arith module is useful here *)
...
Qed.
(* Final theorem *)
Theorem foo X : forall (l : list X), l = rev l -> bar l.
Proof.
intros; apply foo_len; auto.
Qed.
这是一个比 更常见和系统的原理delist
,但是您需要比上面的 ad-hoc 归纳类型工作更多才能在主要证明中使用归纳假设。
推荐阅读
- julia - 使用限制器批量下载数据
- mysql - 如何使用自定义设置在无人值守的情况下安装 MySQL?
- python - Python OpenCV--MAC 网络摄像头不关闭
- string - 在 Mac OS 上的 shell 脚本中将字符串的第一个字符从大写转换为小写的正确方法是什么?
- xcode - React Native 如何更改 iOS 包标识符?
- ubuntu-16.04 - Pygobject 构建失败
- javascript - 重新加载页面时,如何使用现有数据刷新 Google 地图标记和地图?
- php - tenants.php 路由文件指向根目录
- bash - 使用进程替换与管道有什么区别?
- vba - 我试图让这个宏包括从工作簿中的多个工作表复制数据的能力,但它只会从第一个工作表复制