(* 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 Znth_rebase : forall {A} {d : Inhabitant A} (m : list A) i j, 0 <= i < Zlength m -> 0 <= j < Zlength m -> Znth i (rebase m j) = Znth ((i + j) mod Zlength m) m.