Ocaml哈希表中的平等

时间:2012-01-23 13:42:57

标签: hashtable ocaml equality

在测试密钥是否相等时,Ocaml中是否存在使用==而不是=的哈希表? 例如:

# type foo = A of int;;
# let a = A(1);;
# let b = A(1);;
# a == b;;
- : bool = false
# a = b;;
- : bool = true
# let h = Hashtbl.create 8;;
# Hashtbl.add h a 1;;
# Hashtbl.add h b 2;;
# Hashtbl.find h a;;
- : int = 2
# Hashtbl.find h b;;
- : int = 2

我想要一个可以区分ab的哈希表。这可能吗?

2 个答案:

答案 0 :(得分:11)

您可以使用自定义哈希表:

module H = Hashtbl.Make(struct
  type t = foo
  let equal = (==)
  let hash = Hashtbl.hash
end)

然后在代码中使用H代替Hashtbl

答案 1 :(得分:4)

Thomas和cago的答案中的解决方案在功能上是正确的。如果您按原样使用解决方案,可能会给您带来麻烦的一个问题是,如果您散列许多等于(=)(==)不同的密钥,则会产生比预期更多的冲突。实际上,所有(=)相同的密钥都具有Hashtbl.hash的相同哈希值,并最终位于同一个桶中,它们被识别为不同(因为您要求(==)用作相等函数)并创建不同的绑定。在最糟糕的情况下,哈希表的行为与关联列表的复杂程度相同(顺便说一句,这是您可能正在使用的另一种数据结构,然后您不必担心提供哈希函数)。

如果您可以接受偶尔更改值的键(因此无法从哈希表中检索该值,因为绑定在错误的桶中),您可以使用以下低级函数作为散列:

external address_of_value: 'a -> int = "address_of_value"

在C中实现:

#include "caml/mlvalues.h"

value address_of_value(value v)
{
  return (Val_long(((unsigned long)v)/sizeof(long)));
}

然后您将使用:

module H = Hashtbl.Make(struct
  type t = foo 
  let equal = (==) 
  let hash = address_of_value
end);;