(* Abstract properties of hashtables *)
Class hash_fun := { size : Z; hash : Z -> Z; size_pos : size > 0; hash_range : forall i, 0 <= hash i < size }.(* Abstract properties of hashtables *)
Class hash_fun := { size : Z; hash : Z -> Z; size_pos : size > 0; hash_range : forall i, 0 <= hash i < size }.(* Abstract properties of hashtables *)
Class hash_fun := { size : Z; hash : Z -> Z; size_pos : size > 0; hash_range : forall i, 0 <= hash i < size }.(* Abstract properties of hashtables *)
Class hash_fun := { size : Z; hash : Z -> Z; size_pos : size > 0; hash_range : forall i, 0 <= hash i < size }.(* Abstract properties of hashtables *)
Class hash_fun := { size : Z; hash : Z -> Z; size_pos : size > 0; hash_range : forall i, 0 <= hash i < size }.Definition rebase {A} (m : list A) i := rotate m (Zlength m - i) (Zlength m).Definition well_chained (m : list (Z * Z)) := forall k i, index_of (rebase m (hash k)) k = Some i ->
  Forall (fun x => fst x <> 0) (sublist 0 i (rebase m (hash k))).Definition wf_map (m : list (Z * Z)) := NoDup (map fst m).Definition indices i j := (map (fun x => (i + x) mod size) (upto (Z.to_nat ((j - i) mod size)))).Definition lookup (m : list (Z * Z)) (k : Z) :=
  option_map (fun i => (i + hash k) mod size) (index_of' (rebase m (hash k)) k).Definition set m k v := option_map (fun i => upd_Znth i m (k, v)) (lookup m k).Definition get m k := match lookup m k with Some i => let '(k', v') := Znth i m in
  if eq_dec k' 0 then None else Some v' | None => None end.

Lemma index_of'_spec : forall k m, match index_of' m k with | Some i => 0 <= i < Zlength m /\ (fst (Znth i m) = k \/ fst (Znth i m) = 0) /\ Forall (fun x => fst x <> 0 /\ fst x <> k) (sublist 0 i m) | None => ~In k (map fst m) /\ ~In 0 (map fst m) end.