一切都比平时因为Program Fixpoint
,不定义功能,你会采用了经典的Fixpoint
期待,因为它需要找到定义它的结构递归的方式更加复杂。 division
究竟是什么,隐藏在division_func
中。
因此,要操纵你的功能,你需要证明基本的引理,包括一个说明你的功能可以被它的身体取代的基本引理。
Lemma division_eq : forall m n, division m n = match lt_nat 0 n with
| false => 0
| true => match leq_nat n m with
| false => 0
| true => S (division (menos m n) n)
end
end.
现在,问题是如何证明这个结果。这是我认识的唯一解决方案,我认为它非常令人不满。
我使用位于Program.Wf
,或fix_sub_eq_ext
在Program.Wf.WfExtensionality
战术fix_sub_eq
。
这给了像:
Proof.
intros.
unfold division. unfold division_func at 1.
rewrite fix_sub_eq; repeat fold division_func.
- simpl. destruct (lt_nat 0 n) eqn:H.
destruct (leq_nat n m) eqn:H0. reflexivity.
reflexivity. reflexivity.
但第二个目标是相当复杂的。解决这个问题的简单方法是使用公理proof_irrelevance
和functional_extensionality
。应该可以证明这个特定的子目标没有任何公理,但我还没有找到正确的方法来做到这一点。您可以使用第二种策略fix_sub_eq_ext
直接调用它们,而不是手动应用公理,而只为您设定一个目标。
Proof.
intros.
unfold division. unfold division_func at 1.
rewrite fix_sub_eq_ext; repeat fold division_func.
simpl. destruct (lt_nat 0 n) eqn:H.
destruct (leq_nat n m) eqn:H0. reflexivity.
reflexivity. reflexivity.
Qed.
我还没有找到一个更好的方式来使用Program Fixpoint
,这就是为什么我更喜欢使用Function
,它具有其他默认设置,而是直接生成公式引理。
Require Recdef.
Function division (m:nat) (n:nat) {measure (fun n => n) m} : nat :=
match lt_nat 0 n with
| false => 0
| true => match leq_nat n m with
| false => 0
| true => S (division (menos m n) n)
end
end.
Proof.
intros m n. revert m. induction n; intros.
- discriminate teq.
- destruct m. discriminate teq0.
simpl. destruct n. destruct m; apply le_n.
transitivity m. apply IHn. reflexivity. assumption. apply le_n.
Qed.
Check division_equation.
现在你有方程引理,你可以用它和原来一样重写。
关于你的问题destruct
,destruct
不展开定义。因此,如果你没有出现任何目标或任何假设,那么destruct
就不会做任何有趣的事情,除非你保存它产生的等式。您可以使用destruct ... eqn:H
来达到此目的。我不知道case_eq
,但它似乎做同样的事情。
更新:我发现通过使用策略'case_eq(leq_nat n m)'我可以实现我需要的案例分析。然而,我仍然无法弄清楚如何运用划分的定义,即如何展开它并在证明中减少它。 –