【发布时间】:2017-02-16 21:43:32
【问题描述】:
按照 Chlipala 书 GeneralRec 章节中给出的示例,我正在尝试编写归并排序算法。
这是我的代码
Require Import Nat.
Fixpoint insert (x:nat) (l: list nat) : list nat :=
match l with
| nil => x::nil
| y::l' => if leb x y then
x::l
else
y::(insert x l')
end.
Fixpoint merge (l1 l2 : list nat) : list nat :=
match l1 with
| nil => l2
| x::l1' => insert x (merge l1' l2)
end.
Fixpoint split (l : list nat) : list nat * list nat :=
match l with
| nil => (nil,nil)
| x::nil => (x::nil,nil)
| x::y::l' =>
let (ll,lr) := split l' in
(x::ll,y::lr)
end.
Definition lengthOrder (l1 l2 : list nat) :=
length l1 < length l2.
Theorem lengthOrder_wf : well_founded lengthOrder.
Admitted.
问题是无法使用命令Fixpoint 编写mergeSort 函数,因为该函数在结构上没有递减:
Fixpoint mergeSort (l: list nat) : list nat :=
if leb (length l) 1 then l
else
let (ll,lr) := split l in
merge (mergeSort ll) (mergeSort lr).
相反,可以将命令Program Fixpoint 或Definition 与术语Fix 一起使用(如Chlipala 书中所述)。
但是,如果我正在写这篇文章
Definition mergeSort : list nat -> list nat.
refine (Fix lengthOrder_wf (fun (l: list nat) => list nat)
(fun (l : list nat) => (fun mergeSort : (forall ls : list nat, lengthOrder ls l -> list nat )=>
if leb (length l) 1 then
let (ll,lr) := split l in
merge (mergeSort ll _) (mergeSort lr _)
else
l))).
我正在实现不可能的目标:
2 subgoals, subgoal 1 (ID 65)
l : list nat
mergeSort : forall ls : list nat, lengthOrder ls l -> list nat
ll, lr : list nat
============================
lengthOrder ll l
subgoal 2 (ID 66) is:
lengthOrder lr l
这就是为什么 Chlipala 建议以这种方式更改 mergeSort 的定义:
Definition mergeSort : list nat -> list nat.
refine (Fix lengthOrder_wf (fun _ => list nat)
(fun (ls : list nat)
(mergeSort : forall ls' : list nat, lengthOrder ls' ls -> list nat) =>
if Compare_dec.le_lt_dec 2 (length ls)
then let lss := split ls in
merge (mergeSort (fst lss) _) (mergeSort (snd lss) _)
else ls)).
产生以下目标:
2 subgoals, subgoal 1 (ID 68)
ls : list nat
mergeSort : forall ls' : list nat, lengthOrder ls' ls -> list nat
l : 2 <= length ls
lss := split ls : list nat * list nat
============================
lengthOrder (fst lss) ls
subgoal 2 (ID 69) is:
lengthOrder (snd lss) ls
这个新定义对我来说听起来很神奇。所以我想知道:
- 从第一个定义开始,是否还可以证明函数的充分性?
- 否则为什么第一个定义不起作用?
- 基本用户如何轻松地从第一个定义转到第二个定义?
【问题讨论】:
-
length (fst (split l)) < length l是可证明的!观察你在上下文中有H : 2 <= length l。您链接的 CPDT 章节中的split_wf1引理在这里非常有用:Lemma split_wf1 : forall ls, 2 <= length ls -> lengthOrder (fst (split ls)) ls。
标签: coq