我的目的是证明所生成列表的某些属性成立。 例如,一个生成器函数产生一个1s的列表,该列表的长度作为参数给出;我想证明列表的长度是参数指定的长度。这是我到目前为止的内容:
Require Import List.
Fixpoint list_gen lng acc :=
match lng with
0 => acc
| S lng_1 => list_gen (lng_1) (1::acc)
end.
Lemma lm0 : length(list_gen 0 nil) = 0.
intuition.
Qed.
Lemma lm1 : forall lng:nat, length(list_gen lng nil) = lng.
induction lng.
apply lm0.
现在应用lm0后,剩下的归纳步骤是:
1 subgoal
lng : nat
IHlng : length (list_gen lng nil) = lng
______________________________________(1/1)
length (list_gen (S lng) nil) = S lng
我希望从list_gen的代码中推断出这一步的证据,但这很可能是一个错误的概念。如何证明此子目标?
答案 0 :(得分:2)
我会采用Daniel的方法,但是更通用的方法是写出list_gen
的规范,例如使用 non-tail-recursive repeat
函数:
Require Import List Arith.
Import ListNotations.
Lemma list_gen_spec : forall lng acc, list_gen lng acc = repeat 1 lng ++ acc.
Proof.
induction lng as [| lng IH]; intros xs; simpl; trivial.
rewrite IH.
now rewrite app_cons_middle, repeat_singleton, repeat_app, Nat.add_comm.
Qed.
我必须在其中添加关于repeat
与某些标准列表函数的交互作用的引理。
Lemma repeat_singleton {A} (x : A) :
[x] = repeat x 1.
Admitted.
Lemma repeat_app {A} (x : A) n m :
repeat x n ++ repeat x m = repeat x (n + m).
Admitted.
Lemma app_cons {A} (x : A) xs :
x :: xs = [x] ++ xs.
Admitted. (* this is a convenience lemma for the next one *)
Lemma app_cons_middle {A} (y : A) xs ys :
xs ++ y :: ys = (xs ++ [y]) ++ ys.
Admitted.
我将这些引理的证明留作练习。
证明规格后,只需几次重写即可证明您的引理。
Lemma lm1 lng : length(list_gen lng nil) = lng.
Proof.
now rewrite list_gen_spec, app_nil_r, repeat_length.
Qed.