End TrivialDict.
(* dictionaries based on searchtrees we require a total decidable order on keys *)
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.
(* search trees definitions and properties *)
(* the underlying data structure : binary trees labeled with keys and associated values *)
Inductive btree : Set :=
| leaf : btree
| bnode : key -> data -> btree -> btree -> btree.
(* The entry with key k and value v occurs in the binary tree t *)
Inductive occ (v : data) (k : key) : btree -> Prop :=
| occ_root : forall t1 t2 : btree, occ v k (bnode k v t1 t2)
| occ_l :
forall (k' : key) (v' : data) (t1 t2 : btree),
occ v k t1 -> occ v k (bnode k' v' t1 t2)
| occ_r :
forall (k' : key) (v' : data) (t1 t2 : btree),
occ v k t2 -> occ v k (bnode k' v' t1 t2).
(*  key k is less than every key in t  *)
Inductive min (k : key) (t : btree) : Prop :=
min_intro :
(forall (k' : key) (v : data), occ v k' t -> Key.lt k k') -> min k t.
Hint Resolve min_intro: searchtrees.
(*  key k is gretaer than every key in t  *)
Inductive maj (k : key) (t : btree) : Prop :=
maj_intro :
(forall (k' : key) (v : data), occ v k' t -> Key.lt k' k) -> maj k t.
Hint Resolve maj_intro: searchtrees.
(* searchness predicate on binary trees *)
Inductive search_tree : btree -> Prop :=
| leaf_search_tree : search_tree leaf
| bnode_search_tree :
forall (k : key) (v : data) (t1 t2 : btree),
search_tree t1 ->
search_tree t2 ->
maj k t1 -> min k t2 -> search_tree (bnode k v t1 t2).
Inductive is_bnode : btree -> Prop :=
is_bnode_intro :
forall (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
(forall (k k' : key) (v v' : data) (t1 t2 : btree),
occ v' k' (bnode k v t1 t2)).

(* Specifications: *)
Lemma occ_inv :
forall (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.