在测试密钥是否相等时,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
我想要一个可以区分a
和b
的哈希表。这可能吗?
答案 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);;