Library Dictionaries.dict



Require Import Relations.
Require Import List.


Module Type DICT.
 Parameter key : Set.
 Parameter data : Set.  Parameter dict : Set.  Parameter empty : dict.  Parameter add : keydatadictdict.  Parameter find : keydictoption data.

 Axiom empty_def : k : key, find k empty = None.
 Axiom
   success :
      (d : dict) (k : key) (v : data), find k (add k v d) = Some v.
 Axiom
   diff_key :
      (d : dict) (k k' : key) (v : data),
     k k'find k (add k' v d) = find k d.
End DICT.

Module Type DICT_PLUS.
 Declare Module Dict : DICT.
 Parameter build : list (Dict.key × Dict.data) → Dict.dict.
End DICT_PLUS.

Module Dict_Plus (D: DICT) : DICT_PLUS with Module Dict := D.
 Module Dict := D.
 Definition key := D.key.
 Definition data := D.data.
 Definition dict := D.dict.
 Definition add := D.add.
 Definition empty := D.empty.

 Fixpoint addlist (l : list (key × data)) : dictdict :=
   fun d : dict
   match l with
   | nild
   | p :: l'match p with
                | (k, v)addlist l' (add k v d)
                end
   end.

 Definition build (l : list (key × data)) := addlist l empty.
End Dict_Plus.


Module Type KEY.
 Parameter A : Set.
 Parameter eqdec : a b : A, {a = b} + {a b}.
End KEY.

Module LKey (K: KEY) : KEY with Definition A := list K.A.
 Definition A := list K.A.

 Definition eqdec : a b : A, {a = b} + {a b}.
  intro a; elim a.
  simple induction b; [ left; auto | right; red in |- *; discriminate 1 ].
  intros a0 k Ha; simple induction b.
  right; red in |- *; discriminate 1.
  intros a1 l0 s; case (K.eqdec a0 a1); intro H0.
  case (Ha l0); intro H1.
  left; rewrite H1; rewrite H0; auto.
  right; red in |- *; injection 1.
  intro H3; case (H1 H3).
  right; red in |- *; injection 1.
  intros H3 H4; case (H0 H4).
 Defined.
End LKey.

Require Import ZArith.
Module ZKey : KEY with Definition A := Z.
  Definition A := Z.
  Definition eqdec := Z_eq_dec.
End ZKey.

Module LZKey := LKey ZKey.



Module PairKey (K1: KEY) (K2: KEY) : KEY with Definition
  A := (K1.A × K2.A)%type.
 Definition A := (K1.A × K2.A)%type.

 Definition eqdec : a b : A, {a = b} + {a b}.
    simple destruct a.
    intros a0 a1; simple destruct b; intros b0 b1.
    case (K1.eqdec a0 b0); intro H; case (K2.eqdec a1 b1); intro H0;
     [ left | right | right | right ]; try (rewrite H; rewrite H0; trivial);
     red in |- *; intro H1; injection H1; tauto.
 Defined.
End PairKey.


Module Type DEC_ORDER.
 Parameter A : Set.
 Parameter le : AAProp.
 Parameter lt : AAProp.
 Axiom ordered : order A le.
 Axiom lt_le_weak : a b : A, lt a ble a b.
 Axiom lt_diff : a b : A, lt a ba b.
 Axiom le_lt_or_eq : a b : A, le a blt a b a = b.
 Parameter lt_eq_lt_dec : a b : A, {lt a b} + {a = b} + {lt b a}.
End DEC_ORDER.


Module Type MORE_DEC_ORDERS.
  Parameter A : Set.
  Parameter le : AAProp.
  Parameter lt : AAProp.
  Axiom le_trans : transitive A le.
  Axiom le_refl : reflexive A le.
  Axiom le_antisym : antisymmetric A le.
  Axiom lt_irreflexive : a : A, ¬ lt a a.
  Axiom lt_trans : transitive A lt.
  Axiom lt_not_le : a b : A, lt a b¬ le b a.
  Axiom le_not_lt : a b : A, le a b¬ lt b a.
  Axiom lt_intro : a b : A, le a ba blt a b.
  Parameter le_lt_dec : a b : A, {le a b} + {lt b a}.
  Parameter le_lt_eq_dec : a b : A, le a b{lt a b} + {a = b}.
End MORE_DEC_ORDERS.


Module More_Dec_Orders (D: DEC_ORDER) : MORE_DEC_ORDERS with Definition
  A := D.A with Definition le := D.le with Definition lt := D.lt.

 Definition A := D.A.
 Definition le := D.le.
 Definition lt := D.lt.

 Theorem le_trans : transitive A le.
 Proof.
   case D.ordered; auto.
 Qed.

 Theorem le_refl : reflexive A le.
  Proof.
   case D.ordered; auto.
 Qed.

 Theorem le_antisym : antisymmetric A le.
 Proof.
   case D.ordered; auto.
 Qed.

 Theorem lt_intro : a b : A, le a ba blt a b.
 Proof.
   intros a b H diff; case (D.le_lt_or_eq a b H); tauto.
 Qed.

 Theorem lt_irreflexive : a : A, ¬ lt a a.
 Proof.
  intros a H.
  case (D.lt_diff _ _ H); trivial.
 Qed.

 Theorem lt_not_le : a b : A, lt a b¬ le b a.
 Proof.
  intros a b H H0.
  absurd (a = b).
  apply D.lt_diff; trivial.
  apply le_antisym; auto; apply D.lt_le_weak; assumption.
 Qed.

 Theorem le_not_lt : a b : A, le a b¬ lt b a.
 Proof.
   intros a b H H0; apply (lt_not_le b a); auto.
  Qed.

  Theorem lt_trans : transitive A lt.
  Proof.
   unfold A, transitive in |- ×.
   intros x y z H H0.
   apply (lt_intro x z).
   apply le_trans with y; apply D.lt_le_weak; assumption.
   intro e; rewrite e in H.
   absurd (y = z).
   intro e'; rewrite e' in H.
   apply (lt_irreflexive _ H).
   apply le_antisym; apply D.lt_le_weak; trivial.
  Qed.

  Definition le_lt_dec : a b : A, {le a b} + {lt b a}.
   intros a b; case (D.lt_eq_lt_dec a b).
   intro d; case d; auto.
   left; apply D.lt_le_weak; trivial.
   simple induction 1; left; apply le_refl.
   right; trivial.
  Defined.

  Definition le_lt_eq_dec : a b : A, le a b{lt a b} + {a = b}.
   intros a b H.
   case (D.lt_eq_lt_dec a b).
   trivial.
   intro H0; case (le_not_lt a b H H0).
  Defined.

End More_Dec_Orders.

Module Forget_Order (D: DEC_ORDER) : KEY with Definition A := D.A.

 Module M := More_Dec_Orders D.

 Definition A := D.A.

 Definition eqdec : a b : A, {a = b} + {a b}.
  intros a b; case (D.lt_eq_lt_dec a b).
  intro H; case H.
  right; apply D.lt_diff; auto.
  left; trivial.
  intro d; right.
  intro e; rewrite e in d.
  apply (M.lt_irreflexive b); auto.
 Defined.
End Forget_Order.


Module Lexico (D1: DEC_ORDER) (D2: DEC_ORDER) <: DEC_ORDER with Definition
  A := (D1.A × D2.A)%type.

 Module M1 := More_Dec_Orders D1.
 Module M2 := More_Dec_Orders D2.

 Definition A := (D1.A × D2.A)%type.

 Definition le (a b : A) : Prop :=
   let (a1, a2) := a in
   let (b1, b2) := b in D1.lt a1 b1 a1 = b1 D2.le a2 b2.

 Definition lt (a b : A) : Prop :=
   let (a1, a2) := a in
   let (b1, b2) := b in D1.lt a1 b1 a1 = b1 D2.lt a2 b2.

 Theorem ordered : order A le.
 Proof.
  split.
  unfold reflexive in |- *; intros.
  unfold le in |- *; case x.
  right.
  split; [ trivial | apply M2.le_refl; auto ].
  unfold le, transitive in |- ×.
  simple destruct x; simple destruct y; simple destruct z.
  simple destruct 1; intro H1.
  simple destruct 1.
  left.
  eapply M1.lt_trans.
  eexact H1.
  assumption.
  simple destruct 1.
  simple destruct 1.
  auto.
  simple destruct 1.
  intro.
  case H1; intros e H3; rewrite e; auto.
  case H1; intros e H3; rewrite e; auto.
  simple destruct 1.
  simple destruct 1.
  right.
  split; try auto.
  eapply M2.le_trans; eauto.
  unfold antisymmetric, A, le in |- ×.
  simple destruct x; simple destruct y.
  simple destruct 1; simple destruct 2.
  intro.
  absurd (D1.lt a1 a1).
  apply M1.lt_irreflexive.
  eapply M1.lt_trans; eauto.
  simple destruct 1; intros e H3.
  rewrite e in H0.
  case (M1.lt_irreflexive a H0).
  case H0; intros e H3.
  rewrite e; intro H2.
  case (M1.lt_irreflexive a1 H2).
  simple destruct 1; intros e H3; rewrite e.
  case (M2.le_antisym a2 a0).
  auto.
  case H0; auto.
  auto.
 Qed.

 Theorem lt_le_weak : a b : A, lt a ble a b.
 Proof.
  unfold A, lt, le in |- *; intros a b; case a; case b.
  simple destruct 1; intros; auto.
  right; case H0; split; auto.
  apply D2.lt_le_weak; trivial.
 Qed.

 Theorem lt_diff : a b : A, lt a ba b.
 Proof.
  unfold A, lt, le in |- *; intros a b; case a; case b.
  simple destruct 1.
  intro H0; red in |- *; injection 1.
  intros e1 e2; rewrite e2 in H0.
  case (M1.lt_irreflexive a0 H0).
  simple destruct 1.
  simple destruct 1.
  intro H2; red in |- *; injection 1.
  intro e; rewrite e in H2; case (M2.lt_irreflexive _ H2).
 Qed.

 Theorem le_lt_or_eq : a b : A, le a blt a b a = b.
 Proof.
  unfold A, lt, le in |- *; intros a b; case a; case b.
  simple destruct 1; auto.
  simple destruct 1.
  simple destruct 1.
  intro H2; case (D2.le_lt_or_eq _ _ H2).
  auto.
  simple destruct 1.
  auto.
 Qed.

 Definition lt_eq_lt_dec : a b : A, {lt a b} + {a = b} + {lt b a}.
  Proof.
   unfold A, lt in |- *; intros.
   case a; case b.
   intros a0 a1 a2 a3.
   case (D1.lt_eq_lt_dec a0 a2).
   simple destruct 1.
   right.
   auto.
   simple destruct 1.
   case (D2.lt_eq_lt_dec a1 a3).
   simple destruct 1.
   right.
   auto.
   simple destruct 1.
   left; right; trivial.
   left; left; auto.
   left.
   left; auto.
  Defined.
End Lexico.


Module Sum_Order (O1: DEC_ORDER) (O2: DEC_ORDER) <: DEC_ORDER with Definition
  A := (O1.A + O2.A)%type.

 Definition A := (O1.A + O2.A)%type.

 Definition le (a b : A) : Prop :=
   match a with
   | inl a'match b with
               | inl b'O1.le a' b'
               | _True
               end
   | inr a'match b with
               | inr b'O2.le a' b'
               | _False
               end
   end.

  Definition lt (a b : A) : Prop :=
    match a with
    | inl a'match b with
                | inl b'O1.lt a' b'
                | _True
                end
    | inr a'match b with
                | inr b'O2.lt a' b'
                | _False
                end
    end.

 Module M1 := More_Dec_Orders O1.
 Module M2 := More_Dec_Orders O2.

 Theorem ordered : order A le.
 Proof.
  split.
  unfold reflexive in |- *; intros.
  unfold le in |- ×.
  case x.
  exact M1.le_refl.
  exact M2.le_refl.
  unfold le in |- ×.
  unfold transitive in |- ×.
  simple destruct x; simple destruct y; simple destruct z.
  intros; eapply M1.le_trans; eauto.
  auto.
  contradiction.
  auto.
  auto.
  contradiction.
  auto.
  intros; eapply M2.le_trans; eauto.
  unfold antisymmetric, A, le in |- ×.
  simple destruct x; simple destruct y.
  intros a0 H0 H1; rewrite (M1.le_antisym _ _ H0 H1).
  trivial.
  contradiction.
  contradiction.
  intros a0 H0 H1; rewrite (M2.le_antisym _ _ H0 H1).
  trivial.
 Qed.

 Theorem lt_le_weak : a b : A, lt a ble a b.
 Proof.
   unfold A, lt, le in |- *; intros a b.
   case a; case b; auto.
   intros; apply O1.lt_le_weak; trivial.
   intros; apply O2.lt_le_weak; trivial.
 Qed.

 Theorem lt_diff : a b : A, lt a ba b.
 Proof.
    unfold lt in |- *; simple destruct a; simple destruct b.
    intros a1 H e; injection e; intro e'.
    case (O1.lt_diff _ _ H e').
    intros a1 H e; discriminate e.
    contradiction.
    intros a1 H e; injection e; intro e'.
    case (O2.lt_diff _ _ H e').
 Qed.

 Theorem le_lt_or_eq : a b : A, le a blt a b a = b.
 Proof.
   unfold A, lt, le in |- *; intros a b; case a; case b.
   intros a0 a1 H; case (O1.le_lt_or_eq a1 a0 H).
   auto.
   simple destruct 1; auto.
   auto.
   contradiction.
   intros a0 a1 H; case (O2.le_lt_or_eq a1 a0 H); auto.
   simple destruct 1; auto.
 Qed.

 Definition lt_eq_lt_dec : a b : A, {lt a b} + {a = b} + {lt b a}.
  unfold A, lt in |- *; intros.
  case a; case b.
  intros a0 a1.
  case (O1.lt_eq_lt_dec a0 a1).
  simple destruct 1.
  right.
  auto.
  simple destruct 1.
  left.
  right.
  trivial.
  left.
  left.
  trivial.
  left; trivial.
  left; trivial.
  right.
  auto.
  intros a0 a1.
  case (O2.lt_eq_lt_dec a0 a1).
  simple destruct 1.
  right.
  auto.
  simple destruct 1.
  left.
  right.
  trivial.
  left.
  left.
  trivial.
 Defined.

End Sum_Order.

Require Import Arith.

Module Nat_Order : DEC_ORDER with Definition A := nat with Definition
  le := le with Definition lt := lt.
  Definition A := nat.
  Definition le := le.
  Definition lt := lt.
  Theorem ordered : order A le.
  Proof.
    split.
    unfold A, le, reflexive in |- *; auto with arith.
    unfold A, le, transitive in |- *; eauto with arith.
    unfold A, le, antisymmetric in |- *; eauto with arith.
  Qed.

  Theorem lt_le_weak : a b : A, lt a ble a b.
  Proof.
   unfold A in |- *; exact lt_le_weak.
  Qed.

  Theorem lt_diff : a b : A, lt a ba b.
  Proof.
   unfold A, lt, le in |- *; intros a b H e.
   rewrite e in H.
   case (lt_irrefl b H).
  Qed.

  Theorem le_lt_or_eq : a b : A, le a blt a b a = b.
  Proof.
   unfold A, le, lt in |- ×.
   exact le_lt_or_eq.
  Qed.

  Definition lt_eq_lt_dec : a b : A, {lt a b} + {a = b} + {lt b a} :=
    lt_eq_lt_dec.

End Nat_Order.


 Definition bool_le (b b' : bool) :=
   if b then if b' then True else False else True.
 Definition bool_lt (b b' : bool) :=
   if b then False else if b' then True else False.

 Module Bool_Order : DEC_ORDER with Definition A := bool with Definition
   le := bool_le with Definition lt := bool_lt.
  Definition A := bool.
  Definition le := bool_le.
  Definition lt := bool_lt.

  Theorem ordered : order A le.
  Proof.
    split.
    unfold A, le, reflexive in |- ×.
    intro x; case x; simpl in |- *; auto.
    unfold A, le, transitive in |- *; simple destruct x; simple destruct y;
     auto; simple destruct z; auto.
    unfold A, le, antisymmetric in |- *; simple destruct x; simple destruct y;
     simpl in |- *; auto; contradiction.
  Qed.

  Theorem lt_le_weak : a b : A, lt a ble a b.
  Proof.
   unfold A, lt, le in |- *; simple destruct a; simple destruct b;
    simpl in |- *; tauto.
  Qed.

  Theorem lt_diff : a b : A, lt a ba b.
  Proof.
    unfold A, lt, bool_lt in |- *; simple destruct a; simple destruct b; auto.
  Qed.

  Theorem le_lt_or_eq : a b : A, le a blt a b a = b.
  Proof.
   unfold A, le, lt, bool_lt in |- *; simple destruct a; simple destruct b;
    auto.
  Qed.

 Definition lt_eq_lt_dec : a b : A, {lt a b} + {a = b} + {lt b a}.
    unfold A, le, lt, bool_lt in |- *; simple destruct a; simple destruct b;
     auto.
 Defined.
End Bool_Order.


Module Type DATA.
 Parameter data : Set.
End DATA.


Module TrivialDict (Key: KEY) (Val: DATA) : DICT with Definition key := Key.A
  with Definition data := Val.data.
 Definition key := Key.A.
 Definition data := Val.data.
 Definition dict := keyoption data.

 Definition empty (k : key) := None (A:=data).
 Definition find (k : key) (d : dict) := d k.
 Definition add (k : key) (v : data) (d : dict) : dict :=
   fun k' : key
   match Key.eqdec k' k with
   | left _Some v
   | right _d k'
   end.

 Theorem empty_def : k : key, find k empty = None.
 Proof.
  unfold find, empty in |- *; auto.
 Qed.

 Theorem success :
   (d : dict) (k : key) (v : data), find k (add k v d) = Some v.
 Proof.
  unfold find, add in |- *; intros d k v.
  case (Key.eqdec k k); simpl in |- *; tauto.
 Qed.

 Theorem diff_key :
   (d : dict) (k k' : key) (v : data),
  k k'find k (add k' v d) = find k d.
 Proof.
  unfold find, add in |- *; intros d k k' v.
  case (Key.eqdec k k'); simpl in |- *; tauto.
 Qed.

End TrivialDict.


Module TDict (Key: DEC_ORDER) (Val: DATA) : DICT with Definition key := Key.A
  with Definition data := Val.data.
 Definition key := Key.A.
 Definition data := Val.data.

 Module M := More_Dec_Orders Key.



 Inductive btree : Set :=
   | leaf : btree
   | bnode : keydatabtreebtreebtree.


 Inductive occ (v : data) (k : key) : btreeProp :=
   | occ_root : t1 t2 : btree, occ v k (bnode k v t1 t2)
   | occ_l :
        (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t1occ v k (bnode k' v' t1 t2)
   | occ_r :
        (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t2occ v k (bnode k' v' t1 t2).

 Inductive min (k : key) (t : btree) : Prop :=
     min_intro :
       ( (k' : key) (v : data), occ v k' tKey.lt k k') → min k t.

 Hint Resolve min_intro: searchtrees.

 Inductive maj (k : key) (t : btree) : Prop :=
     maj_intro :
       ( (k' : key) (v : data), occ v k' tKey.lt k' k) → maj k t.

 Hint Resolve maj_intro: searchtrees.

 Inductive search_tree : btreeProp :=
   | leaf_search_tree : search_tree leaf
   | bnode_search_tree :
        (k : key) (v : data) (t1 t2 : btree),
       search_tree t1
       search_tree t2
       maj k t1min k t2search_tree (bnode k v t1 t2).

 Inductive is_bnode : btreeProp :=
     is_bnode_intro :
        (k : key) (v : data) (t1 t2 : btree),
       is_bnode (bnode k v t1 t2).

 Hint Resolve is_bnode_intro: searchtrees.

 Hint Resolve occ_root occ_l occ_r: searchtrees.

 Derive Inversion_clear OCC_INV with
  ( (k k' : key) (v v' : data) (t1 t2 : btree),
   occ v' k' (bnode k v t1 t2)).

 Lemma occ_inv :
   (k k' : key) (v v' : data) (t1 t2 : btree),
  occ v' k' (bnode k v t1 t2) →
  k = k' v = v' occ v' k' t1 occ v' k' t2.
 Proof.
  intros k k' v v' t1 t2 H.
  inversion H using OCC_INV; auto with searchtrees.
 Qed.

 Hint Resolve occ_inv: searchtrees.

 Lemma not_occ_Leaf : (k : key) (v : data), ¬ occ v k leaf.
 Proof.
  unfold not in |- *; intros k v H.
  inversion_clear H.
 Qed.

 Hint Resolve not_occ_Leaf: searchtrees.

 Hint Resolve leaf_search_tree bnode_search_tree: searchtrees.

 Lemma min_leaf : k : key, min k leaf.
 Proof.
  intro k; apply min_intro.
  inversion_clear 1.
 Qed.

 Hint Resolve min_leaf: searchtrees.

 Lemma maj_leaf : k : key, maj k leaf.
 Proof.
  intro k; apply maj_intro; inversion_clear 1.
 Qed.

 Hint Resolve maj_leaf: searchtrees.

 Lemma maj_not_occ :
   (k : key) (v : data) (t : btree), maj k t¬ occ v k t.
 Proof.
  unfold not in |- *; intros k v t H H'.
  elim H; intros; absurd (Key.lt k k); auto.
  apply M.lt_irreflexive.
  eauto.
 Qed.

 Hint Resolve maj_not_occ: searchtrees.

 Lemma min_not_occ :
   (k : key) (v : data) (t : btree), min k t¬ occ v k t.
 Proof.
  unfold not in |- *; intros k v t H H'.
  elim H; intros; absurd (Key.lt k k); eauto.
  apply M.lt_irreflexive.
 Qed.

 Hint Resolve min_not_occ: searchtrees.


 Section search_tree_basic_properties.

 Variables (n : key) (v : data) (t1 t2 : btree).

 Hypothesis se : search_tree (bnode n v t1 t2).

 Lemma search_tree_l : search_tree t1.
 Proof.
  inversion_clear se; auto with searchtrees.
 Qed.

 Hint Resolve search_tree_l: searchtrees.

 Lemma search_tree_r : search_tree t2.
 Proof.
  inversion_clear se; auto with searchtrees.
 Qed.
 Hint Resolve search_tree_r: searchtrees.

 Lemma maj_l : maj n t1.
 Proof.
  inversion_clear se; auto with searchtrees.
 Qed.
 Hint Resolve maj_l: searchtrees.

 Lemma min_r : min n t2.
 Proof.
  inversion_clear se; auto with searchtrees.
 Qed.

 Hint Resolve min_r: searchtrees.

 Lemma not_right : (p : key) (v' : data), Key.le p n¬ occ v' p t2.
 Proof.
  intros p v' H; elim min_r.
  unfold not in |- *; intros; absurd (Key.lt n p); eauto with searchtrees.
  apply M.le_not_lt; assumption.
 Qed.

 Hint Resolve not_right: searchtrees.

 Lemma not_left : (p : key) (v' : data), Key.le n p¬ occ v' p t1.
 Proof.
  intros p v' H; elim maj_l.
  unfold not in |- *; intros; absurd (Key.lt p n); eauto with searchtrees.
  apply M.le_not_lt; assumption.
 Qed.

 Hint Resolve not_left: searchtrees.

 Lemma go_left :
   (p : key) (v' : data),
  occ v' p (bnode n v t1 t2) → Key.lt p nocc v' p t1.
 Proof.
  intros p v' H H0.
  case (occ_inv _ _ _ _ _ _ H).
  repeat simple destruct 1; absurd (Key.lt p n).
  rewrite H2; apply M.lt_irreflexive.
  assumption.
  simple destruct 1; trivial.
  intro H2; absurd (occ v' p t2).
  apply not_right.
  apply Key.lt_le_weak; assumption.
  auto.
 Qed.

 Lemma go_right :
   (p : key) (v' : data),
  occ v' p (bnode n v t1 t2) → Key.lt n pocc v' p t2.
 Proof.
  intros p v' H H0.
  case (occ_inv _ _ _ _ _ _ H).
  repeat simple destruct 1; absurd (Key.lt n p).
  rewrite H2; apply M.lt_irreflexive.
  assumption.
  simple destruct 1; trivial.
  intro H2; absurd (occ v' p t1).
  apply not_left.
  apply Key.lt_le_weak; assumption.
  auto.
 Qed.

 End search_tree_basic_properties.

 Hint Resolve go_left go_right not_left not_right search_tree_l search_tree_r
   maj_l min_r: searchtrees.


 Lemma occ_unicity :
   t : btree,
  search_tree t
   (k : key) (v v' : data), occ v k tocc v' k tv = v'.
 Proof.   simple induction t.
  inversion 2.
  intros.
  case (occ_inv _ _ _ _ _ _ H2).
  repeat simple destruct 1.
  case (occ_inv _ _ _ _ _ _ H3).
  tauto.
  simple destruct 1.
  intro.
  absurd (occ v' k0 b); auto.
  eapply not_left.
  eauto.
  rewrite H5; apply M.le_refl.
  intro.
  absurd (occ v' k0 b0); auto.
  eapply not_right; eauto.
  rewrite H5; apply M.le_refl.
  simple destruct 1; intro.
  case (occ_inv _ _ _ _ _ _ H3).
  repeat simple destruct 1.
  absurd (occ v k b); auto.
  eapply not_left; eauto.
  apply M.le_refl.
  rewrite H7; auto.
  simple destruct 1; intro.
  eapply H.
  eauto with searchtrees.
  eauto.
  assumption.
  absurd (occ v' k0 b0); auto.
  eapply not_right; eauto with searchtrees.
  case (maj_l _ _ _ _ H1).
  intro; apply Key.lt_le_weak.
  eauto.
  case (occ_inv _ _ _ _ _ _ H3).
  repeat simple destruct 1.
  absurd (occ v k0 b0); auto.
  case H7.
  eapply not_right; eauto with searchtrees.
  apply M.le_refl.
  simple destruct 1.
  intro.
  absurd (occ v' k0 b); auto.
  eapply not_left; eauto with searchtrees.
  case (min_r _ _ _ _ H1).
  intros.
  apply Key.lt_le_weak.
  eauto.
  intro.
  eapply H0.
  eauto with searchtrees.
  eauto.
  eauto.
 Qed.


 Definition occ_dec_spec (k : key) (t : btree) :=
   search_tree t{v : data | occ v k t} + {( v : data, ¬ occ v k t)}.

 Definition occ_dec : (k : key) (t : btree), occ_dec_spec k t.
  intro p; simple induction t.
  right.
  auto with searchtrees.
  intros n v t1 R1 t2 R2 H.
  case (M.le_lt_dec p n).
  intro H0; case (M.le_lt_eq_dec p n H0).
  intro H1; case R1.
  eauto with searchtrees.
  simple destruct 1; intros v' H'.
  left.
   v'; eauto with searchtrees.
  right.
  intros v0 H3.
  apply (n0 v0); eauto with searchtrees.
  simple destruct 1; left.
   v; eauto with searchtrees.
  intro H2; case R2.
  eauto with searchtrees.
  simple destruct 1; intros v' H'.
  left.
   v'; eauto with searchtrees.
  right.
  intros v0 H3.
  apply (n0 v0); eauto with searchtrees.
 Defined.


 Inductive INSERT (n : key) (v : data) (t t' : btree) : Prop :=
     insert_intro :
       ( (p : key) (v' : data), occ v' p tp = n occ v' p t') →
       occ v n t'
       ( (p : key) (v' : data),
        occ v' p t'occ v' p t n = p v = v') →
       search_tree t'INSERT n v t t'.

 Hint Resolve insert_intro: searchtrees.

 Definition insert_spec (n : key) (v : data) (t : btree) : Set :=
   search_tree t{t' : btree | INSERT n v t t'}.

 Lemma insert_leaf :
   (n : key) (v : data), INSERT n v leaf (bnode n v leaf leaf).
 Proof.
  intro n; split; auto with searchtrees.
  intros p k H; inversion_clear H; auto with searchtrees.
 Qed.
 Hint Resolve insert_leaf: searchtrees.


 Lemma insert_l :
   (n p : key) (v v' : data) (t1 t'1 t2 : btree),
  Key.lt n p
  search_tree (bnode p v' t1 t2) →
  INSERT n v t1 t'1INSERT n v (bnode p v' t1 t2) (bnode p v' t'1 t2).
 Proof.
  intros n p v v' t1 t'1 t2 H H0 H1; split.
  intros p0 v'0 H2; inversion_clear H2.
  auto with searchtrees.
  case H1; intros.
  case (H2 _ _ H3).
  auto.
  auto with searchtrees.
  auto with searchtrees.
  case H1; intros.
  eauto with searchtrees.
  intros p0 v'0 H2.
  inversion_clear H2.
  auto with searchtrees.
  case H1; intros.
  elim (H5 p0 v'0); auto with searchtrees.
  auto with searchtrees.
  case H1; constructor 2; auto with searchtrees.
  eapply search_tree_r; eauto with searchtrees.
  split; intros.
  elim (H4 _ _ H6).
  intro.
  cut (maj p t1).
  inversion_clear 1; eauto with searchtrees.
  eauto with searchtrees.
  repeat simple destruct 1.
  assumption.
  eauto with searchtrees.
 Qed.


 Lemma insert_r :
   (n p : key) (v v' : data) (t1 t2 t'2 : btree),
  Key.lt p n
  search_tree (bnode p v' t1 t2) →
  INSERT n v t2 t'2INSERT n v (bnode p v' t1 t2) (bnode p v' t1 t'2).

 Proof.
  intros n p v v' t1 t2 t'2 H H0 H1; split.
  intros p0 v'0 H2; inversion_clear H2.
  auto with searchtrees.
  auto with searchtrees.
  case H1; intros.
  case (H2 _ _ H3).
  auto.
  auto with searchtrees.
  case H1; intros.
  auto with searchtrees.
  intros p0 v'0 H2.
  inversion_clear H2.
  auto with searchtrees.
  auto with searchtrees.
  case H1; intros.
  elim (H5 p0 v'0 H3); auto with searchtrees.
  case H1; constructor 2; auto with searchtrees.
  eapply search_tree_l; eauto with searchtrees.
  eauto with searchtrees.
  split; intros.
  case (H4 _ _ H6).
  intro.
  cut (min p t2).
  inversion_clear 1; eauto with searchtrees.
  eauto with searchtrees.
  repeat simple destruct 1.
  assumption.
 Qed.


 Lemma insert_eq :
   (n : key) (v v' : data) (t1 t2 : btree),
  search_tree (bnode n v t1 t2) →
  INSERT n v' (bnode n v t1 t2) (bnode n v' t1 t2).
 Proof.
  split.
  inversion 1; eauto with searchtrees.
  eauto with searchtrees.
  inversion 1; eauto with searchtrees.
  inversion H; eauto with searchtrees.
 Qed.

 Hint Resolve insert_l insert_r insert_eq: searchtrees.

 Definition insert :
    (n : key) (v : data) (t : btree), insert_spec n v t.
  simple induction t.
   (bnode n v leaf leaf).
  auto with searchtrees.
  unfold insert_spec at 3 in |- *; intros p b t1 H1 t2 H2 H0.
  case (M.le_lt_dec n p).
  intro H; case (M.le_lt_eq_dec n p H).
  intro H'.
  case (H1 (search_tree_l _ _ _ _ H0)).
  intros t3; (bnode p b t3 t2).
  auto with searchtrees.
  intro e; rewrite e; (bnode p v t1 t2); auto with searchtrees.
  case (H2 (search_tree_r _ _ _ _ H0)).
  intros t3; (bnode p b t1 t3).
  auto with searchtrees.
 Defined.



 Definition dict : Set := sig search_tree.

 Definition empty : dict.
  unfold dict in |- *; leaf.
  left.
 Defined.

 Definition find (k : key) (d : dict) : option data :=
   let (t, Ht) := d in
   match occ_dec k t Ht with
   | inleft slet (v, _) := s in Some v
   | inright _None (A:=data)
   end.

 Definition add : keydatadictdict.
  refine
   (fun (k : key) (v : data) (d : dict) ⇒
    let (t, Ht) := d in
    let (x, Hx) := insert k v t Ht in exist search_tree x _).
  case Hx; auto.
 Defined.


 Definition D_tree (d : dict) : btree := match d with
                                         | exist t Htt
                                         end.

 Lemma D_search : d : dict, search_tree (D_tree d).
 Proof.
   simple destruct d; simpl in |- *; auto.
 Qed.

 Lemma find_occ_dec :
   (k : key) (v : data) (d : dict),
  occ v k (D_tree d) → find k d = Some v.

 Proof.
  unfold find in |- *; simple destruct d; simpl in |- *; intros.
  case (occ_dec k x s); simpl in |- ×.
  simple destruct s0; simpl in |- ×.
  intros x0 H0; case (occ_unicity x s _ _ _ H H0).
  auto.
  intros.
  case (n v H).
 Qed.

 Lemma not_find_occ_dec :
   (k : key) (d : dict),
  ( v : data, ¬ occ v k (D_tree d)) → find k d = None.
 Proof.
  unfold find in |- *; simple destruct d; simpl in |- *; intros.
  case (occ_dec k x s); simpl in |- ×.
  simple destruct s0; simpl in |- ×.
  intros.
  case (H _ o).
  auto.
 Qed.

 Theorem empty_def : k : key, find k empty = None.
 Proof.
  unfold find, empty in |- ×.
  intro k; case (occ_dec k leaf leaf_search_tree); simpl in |- ×.
  simple destruct s.
  inversion 1.
  auto.
 Qed.

 Remark success2 :
   (d : dict) (k : key) (v : data), occ v k (D_tree (add k v d)).
 Proof.
  simple destruct d.
  simpl in |- ×.
  intros x s k v; case (insert k v x s); simpl in |- ×.
  simple destruct 1.
  eauto with searchtrees.
 Qed.

 Theorem success :
   (d : dict) (k : key) (v : data), find k (add k v d) = Some v.
 Proof.
  intros; apply find_occ_dec.
  apply success2.
 Qed.

 Remark diff_key1 :
   (d : dict) (k k' : key) (v v' : data),
  k k'occ v k (D_tree (add k' v' d)) → occ v k (D_tree d).
 Proof.
  simple destruct d.
  simpl in |- ×.
  intros x s k k' v v'; case (insert k' v' x s); simpl in |- ×.
  simple destruct 1; intros.
  case (H1 _ _ H4).
  auto.
  simple destruct 1; absurd (k' = k); auto.
  case H5; auto.
 Qed.

 Remark diff_key2 :
   (d : dict) (k k' : key) (v v' : data),
  k k'occ v k (D_tree d) → occ v k (D_tree (add k' v' d)).
 Proof.
  simple destruct d; simpl in |- ×.
  intros x s k k' v v'; case (insert k' v' x s); simpl in |- ×.
  simple destruct 1; intros.
  case (H _ _ H4).
  intro H5; case (H3 H5).
  auto.
 Qed.


 Theorem diff_key :
   (d : dict) (k k' : key) (v : data),
  k k'find k (add k' v d) = find k d.
 Proof.
  intros.
  case (occ_dec k (D_tree d)).
  apply D_search.
  simple destruct 1.
  intros x Hx.
  transitivity (Some x).
  apply find_occ_dec.
  apply diff_key2; auto.
  symmetry in |- *; apply find_occ_dec; auto.
  intro; transitivity (None (A:=data)).
  apply not_find_occ_dec.
  intros v0 H0.
  apply (n v0).
  eapply diff_key1; eauto.
  symmetry in |- *; apply not_find_occ_dec.
  auto.
 Qed.

End TDict.


Module BoolNat := Lexico Bool_Order Nat_Order.

Module MoreBoolNat := More_Dec_Orders BoolNat.

Module Nats <: DATA.
 Definition data := list nat.
End Nats.

Module NaiveDict := TrivialDict LZKey Nats.

Module MyDict : DICT := TDict BoolNat Nats.

Module Dict2 := Dict_Plus MyDict.

Module Dict1 := Dict_Plus NaiveDict.