12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485open!Import(** @canonical Base.Hashable.Key *)moduletypeKey=sigtypet[@@deriving_inlinecompare,sexp_of]includePpx_compare_lib.Comparable.Swithtypet:=tvalsexp_of_t:t->Sexplib0.Sexp.t[@@@end](** Values returned by [hash] must be non-negative. An exception will be raised in the
case that [hash] returns a negative value. *)valhash:t->intendmoduleHashable=structtype'at={hash:'a->int;compare:'a->'a->int;sexp_of_t:'a->Sexp.t}(** This function is sound but not complete, meaning that if it returns [true] then it's
safe to use the two interchangeably. If it's [false], you have no guarantees. For
example:
{[
> utop
open Core;;
let equal (a : 'a Hashtbl_intf.Hashable.t) b =
phys_equal a b
|| (phys_equal a.hash b.hash
&& phys_equal a.compare b.compare
&& phys_equal a.sexp_of_t b.sexp_of_t)
;;
let a = Hashtbl_intf.Hashable.{ hash; compare; sexp_of_t = Int.sexp_of_t };;
let b = Hashtbl_intf.Hashable.{ hash; compare; sexp_of_t = Int.sexp_of_t };;
equal a b;; (* false?! *)
]}
*)letequalab=phys_equalab||(phys_equala.hashb.hash&&phys_equala.compareb.compare&&phys_equala.sexp_of_tb.sexp_of_t);;lethash_param=Stdlib.Hashtbl.hash_paramlethash=Stdlib.Hashtbl.hashletpoly={hash;compare=Poly.compare;sexp_of_t=(fun_->Sexp.Atom"_")}letof_key(typea)(moduleKey:Keywithtypet=a)={hash=Key.hash;compare=Key.compare;sexp_of_t=Key.sexp_of_t};;letto_key(typea){hash;compare;sexp_of_t}=(modulestructtypet=alethash=hashletcompare=compareletsexp_of_t=sexp_of_tend:Keywithtypet=a);;endincludeHashablemoduletypeHashable=sigtype'at='aHashable.t={hash:'a->int;compare:'a->'a->int;sexp_of_t:'a->Sexp.t}valequal:'at->'at->boolvalpoly:'atvalof_key:(moduleKeywithtypet='a)->'atvalto_key:'at->(moduleKeywithtypet='a)valhash_param:int->int->'a->intvalhash:'a->intend