如何在coq中证明ListMap的递归函数定理?
我正在努力学习在Coq中使用如何在coq中证明ListMap的递归函数定理?,coq,coq-tactic,Coq,Coq Tactic,我正在努力学习在Coq中使用ListMap模块。当通过递归函数创建ListMap时,我真的不确定如何证明ListMap中键或值的属性。我觉得我不知道该用什么策略 (* Me proving statements about maps to understand how to use maps in Coq *) Require Import FunInd. Require Import Coq.Lists.List. Require Import Coq.FSets.FMapInterface
ListMap
模块。当通过递归函数创建ListMap
时,我真的不确定如何证明ListMap
中键或值的属性。我觉得我不知道该用什么策略
(* Me proving statements about maps to understand how to use maps in Coq *)
Require Import FunInd.
Require Import Coq.Lists.List.
Require Import Coq.FSets.FMapInterface.
Require Import
Coq.FSets.FMapList
Coq.Structures.OrderedTypeEx.
Module Import MNat := FMapList.Make(Nat_as_OT).
Require Import
Coq.FSets.FMapFacts.
Definition NatToNat := MNat.t nat.
Definition NatToNatEmpty : NatToNat := MNat.empty nat.
(* We wish to show that map will have only positive values *)
Function insertNats (n: nat) (mm: NatToNat) {struct n}: NatToNat :=
match n with
| O => mm
| S (next) => insertNats next (MNat.add n n mm)
end.
Definition keys (mm: NatToNat) : list nat :=
List.map fst (elements mm).
(* vvvvv How do I prove this? Intuitively it is true *)
Example keys_nonnegative: forall (n: nat),
forall (k: nat),
List.In k (keys (insertNats n NatToNatEmpty)) -> k >= 0.
Proof.
intros n k in_proof.
induction n.
simpl in in_proof. tauto.
(* ??? NOW WHAT *)
Admitted.
非正式地说,我将为下面的程序使用的参数是,因为n>=0
,因为它是一个nat
,所以通过idMapsGo
插入到映射中的键也将始终是非负的
我需要为键输入n
\u非负的。在n
步骤中,我们添加了一个键n
,它将是非负的(由于是nat
)。基本情况并不重要
然而,我无法将这种直觉转化为Coq证据:)你想看和从中看
键上的有用属性:
这里有两个关于键定义的有用属性,可以帮助您简化证明。代码取自我自己的项目,其中包括地图上的帮助器属性
Definition keys {elt:Type} (m:t elt) : list key := fst (split (elements m)).
Fixpoint split_alt {A:Type} {B:Type} (l:list (A*B) %type) : (list A * list B) % type:=
match l with
| nil => (nil, nil)
| (x, y) :: l => (x :: (fst (split_alt l)), y :: (snd (split_alt l)))
end.
Lemma split_alt_spec:
forall {A:Type} {B:Type} (l:list (A*B) %type),
split l = split_alt l.
Proof.
intros.
induction l.
- auto.
- simpl. intuition.
rewrite IHl.
remember (split_alt l) as l'.
destruct l' as (lhs, rhs).
auto.
Qed.
Lemma in_fst_split:
forall {A:Type} {B:Type} (l:list (A*B)%type) (lhs:A),
List.In lhs (fst (split l)) ->
exists rhs, List.In (lhs, rhs) l.
Proof.
intros.
induction l.
{ inversion H. (* absurd *) }
destruct a.
rewrite split_alt_spec in H.
simpl in H.
destruct H.
+ subst.
eauto using in_eq.
+ rewrite <- split_alt_spec in H.
apply IHl in H; clear IHl.
destruct H as (r, Hin).
eauto using in_cons.
Qed.
Lemma in_elements_to_in:
forall {elt:Type} k e (m: t elt),
List.In (k, e) (elements m) ->
In k m.
Proof.
intros.
rewrite elements_in_iff.
exists e.
apply InA_altdef.
apply Exists_exists.
exists (k,e).
intuition.
unfold eq_key_elt.
intuition.
Qed.
Lemma keys_spec_1:
forall {elt:Type} (m:t elt) (k:key),
List.In k (keys m) -> In k m.
Proof.
intros.
unfold keys in *.
apply in_fst_split in H.
destruct H as (e, H).
apply in_elements_to_in with (e0:=e).
assumption.
Qed.
Lemma keys_spec_2:
forall {elt:Type} (m:t elt) (k:key),
In k m ->
exists k', E.eq k k' /\ List.In k' (keys m).
Proof.
intros.
unfold keys in *.
destruct H as (e, H).
apply maps_to_impl_in_elements in H.
destruct H as (k', (Heq, Hin)).
apply in_split_l in Hin.
exists k'.
intuition.
Qed.
定义键{elt:Type}(m:telt):列表键:=fst(拆分(元素m))。
固定点拆分{A:Type}{B:Type}(l:list(A*B)%Type):(list A*list B)%Type:=
匹配
|零=>(零,零)
|(x,y)::l=>(x::(fst(split_alt l)),y:(snd(split_alt l)))
结束。
引理拆分替换规范:
对于所有{A:Type}{B:Type}(l:list(A*B)%Type),
拆分l=拆分alt l。
证明。
介绍。
诱导l。
-自动的。
-简单。直觉
重写国际人道主义法。
记住(拆分为l)。
自毁l'as(左、右)。
自动的。
Qed。
分裂中的引理:
对于所有{A:Type}{B:Type}(l:list(A*B)%Type)(lhs:A),
列表。在左侧(fst(拆分l))->
存在rhs,列表。在(左,右)l中。
证明。
介绍。
诱导l。
{H.(*荒谬*)}
破坏a。
重写H中的split_alt_规范。
H中的simple。
破坏H。
+替代品。
eauto在eq中使用。
+重写
在英国。
证明。
介绍。
在\u iff中重写元素\u。
存在e。
应用InA_altdef。
应用存在\u存在。
存在(k,e)。
直觉
打开eq_键。
直觉
Qed。
引理键规范1:
对于所有{elt:Type}(m:t elt)(k:key),
列表。在k中(键m)->在k中。
证明。
介绍。
在*中展开关键点。
应用于H中的fst分割。
将H分解为(e,H)。
用(e0:=e)将in_元素应用到in_中。
假设。
Qed。
引理键规格2:
对于所有{elt:Type}(m:t elt)(k:key),
在k m->
存在k',E.eq k'/\List.In k'(键m)。
证明。
介绍。
在*中展开关键点。
将H分解为(e,H)。
将映射应用于H中的元素。
自毁H为(k’,(Heq,Hin))。
在Hin中申请拆分。
存在k′。
直觉
Qed。
因为“k”是一个“nat”,所以它是非负的。在这种情况下,为什么需要查看地图的内容?你的引理是用“intros.auto with*”作为证明体证明的(不需要归纳)。事实上是这样的。但这不是重点:实际的例子更复杂——我选择创建这个人工的例子。如果有帮助的话,把它看成是Z,而不是NAT。啊,很抱歉混乱。哇,谢谢!我将检查您的证明并了解它是如何工作的,这是非常感谢的:)嗯,我在应用列表中找不到。完整来源可在此处获得:在公共域许可下。