如何在coq中证明ListMap的递归函数定理?

如何在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

我正在努力学习在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.


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。啊,很抱歉混乱。哇,谢谢!我将检查您的证明并了解它是如何工作的,这是非常感谢的:)嗯,我在
应用列表中找不到
。完整来源可在此处获得:在公共域许可下。