Section associative_arrays.
Set Asymmetric Patterns.
Set Strict Implicit.
Unset Implicit Arguments.
Variable K : Set.
Variable V : Set.
Hypothesis Keq_dec : forall x y : K, {x = y} + {x <> y}.
Record Tuple : Set := mkTuple {k : K; v : V}.
(**************************************************)
(* Definitions                                    *)
(**************************************************)
Definition assoc := list Tuple.
(* <Warning> : Syntax is discontinued *)
Definition assoc_empty := nil (A:=Tuple).
(* search function : locate a value by its key *)
Fixpoint assoc_find (l : assoc) : K -> option V :=
fun k0 : K =>
match l with
| nil => none V
| mkTuple k v :: l' =>
match Keq_dec k k0 with
| left _ => some V v
| right _ => assoc_find l' k0
end
end.
(* function to add an entry in an array:  may replace an existing entry if the key is already present in the array *)
Fixpoint assoc_add (l : assoc) : K -> V -> assoc :=
fun (k0 : K) (v0 : V) =>
match l with
| nil => mkTuple k0 v0 :: nil
| mkTuple k v :: l' =>
match Keq_dec k k0 with
| left _ => mkTuple k0 v0 :: l'
| _ => mkTuple k v :: assoc_add l' k0 v0
end
end.
(* remove an entry from an array or do nothing if the key isn't present in the array *)
Fixpoint assoc_delete (l : assoc) : K -> assoc :=
fun k0 : K =>
match l with
| nil => nil (A:=Tuple)
| mkTuple k v :: l' =>
match Keq_dec k k0 with
| left _ => assoc_delete l' k0
| _ => mkTuple k v :: assoc_delete l' k0
end
end.
(* tests the existence of a key in an array *)
Definition assoc_mem (l : assoc) (k : K) : Prop :=
match assoc_find l k with
| some _ => True
| _ => False
end.
(* tests the existence of the specified tuple in an array *)
Definition assoc_hasmem (l : assoc) (k : K) (v : V) : Prop :=
match assoc_find l k with
| some v' => v = v'
| _ => False
end.
(* definition of equal functions from keys to values option *)
Definition assoc_eqm (f1 f2 : K -> option V) := forall k : K, f1 k = f2 k.
(* definition of almost-everywhere-equal functions from keys to values option *)
Definition assoc_almost_eqm (k0 : K) (f1 f2 : K -> option V) :=
forall k : K, k <> k0 -> f1 k = f2 k.
(**************************************************)
(* Some properties about eqm functions            *)
(**************************************************)
(**************************************************)
(* assoc_find properties                          *)
(**************************************************)

Lemma assoc_semfind_commute :
forall (k0 k1 : K) (v0 v1 : V) (l : assoc),
k0 <> k1 ->
assoc_eqm (assoc_find (mkTuple k1 v1 :: mkTuple k0 v0 :: l))
(assoc_find (mkTuple k0 v0 :: mkTuple k1 v1 :: l)).