functor Map.make中合并的OCaml语义?
我正在编写一个OCaml函数,其中需要合并两个映射。我无法理解functorfunctor Map.make中合并的OCaml语义?,ocaml,Ocaml,我正在编写一个OCaml函数,其中需要合并两个映射。我无法理解functorMap.Make(在OCaml的3.12.0版中找到)提供的merge函数的语义。有人能给我一个比OCaml手册更详细的解释吗?一个例子可能足以让我明白这一点 此外,我需要合并的两个映射具有一些有趣的属性:键具有相同的类型(int,实际上),并且它们的域是不相交的。还有比合并例程更有效的方法吗?merge使用一个函数和两个映射。对于任一映射中存在的每个键,将调用该函数。如果键只存在于其中一个映射中,则另一个映射的值将作为
Map.Make
(在OCaml的3.12.0版中找到)提供的merge
函数的语义。有人能给我一个比OCaml手册更详细的解释吗?一个例子可能足以让我明白这一点
此外,我需要合并的两个映射具有一些有趣的属性:键具有相同的类型(
int
,实际上),并且它们的域是不相交的。还有比合并例程更有效的方法吗?merge
使用一个函数和两个映射。对于任一映射中存在的每个键,将调用该函数。如果键只存在于其中一个映射中,则另一个映射的值将作为None传入(这就是为什么参数是选项)。如果函数返回Some x
,则新映射将具有相关密钥的值x
。否则钥匙就不存在了
例如:
let map1 = add 1 2 (add 2 3 empty);;
let map2 = add 2 5 (add 3 4 empty);;
let map3 = merge (fun k xo yo -> match xo,yo with
| Some x, Some y -> Some (x+y)
| _ -> None
) map1 map2;;
map3现在包含映射2->8
如果将其更改为:
let map3 = merge (fun k xo yo -> match xo,yo with
| Some x, Some y -> Some (x+y)
| None, yo -> yo
| xo, None -> xo
) map1 map2;;
它将包含基于第一个答案的映射
1->2
,2->8
和3->4
,,并且考虑到附加问题(在域不相交的情况下合并映射),然后我将提出以下通用合并例程:
let merge_disjoint m1 m2 =
IntMap.merge
(fun k x0 y0 ->
match x0, y0 with
None, None -> None
| None, Some v | Some v, None -> Some v
| _, _ -> invalid_arg "merge_disjoint: maps are not disjoint")
m1 m2
有没有更有效的方法
--David。由于地图是不相交的,因此您可以在较小的地图中循环并插入较大的地图:
let disjoint_merge m1 m2 =
if (IntMap.cardinal m1) < (IntMap.cardinal m2) then
IntMap.fold IntMap.add m1 m2
else
IntMap.fold IntMap.add m2 m1
它基本上遍历映射的所有元素,并调用一个函数,该函数接受键、值和其他类型的变量'b
,并返回该类型的内容('b
)。在本例中,我们传递的是函数IntMap.add
,另一个变量是我们的第二个map。因此它遍历所有元素并将它们添加到另一个映射中
编辑:您最好只做以下操作:
let disjoint_merge m1 m2 =
IntMap.fold IntMap.add m1 m2
编辑2:更好的是:
let disjoint_merge = IntMap.fold IntMap.add;;
我刚刚查看了
cardinal
的实现,它遍历树并返回计数。因此,通过检查您正在执行的大小是O(n+m+min(n,m)log(max(n,m)),而不仅仅是O(nlog(m))。当键的类型是int
并且您对合并(不相交或不相交)贴图感兴趣时,值得检查表示为Patricia树的贴图是否适合您的需要。这里有一个实现:顺便说一句,如果其中一个答案解决了您的问题,您应该将其标记为已接受。这将是一个很好的Map.union
函数。对我来说,合并贴图的想法不仅允许在相同键的情况下应用某些功能,甚至允许在一个贴图中使用键。例如,可能有人想Map.merge(fun x y->(x,y))
我认为对merge的定义有用的一些澄清:merge
将通过m1或m2中的所有键迭代f
,但只保留那些返回值不是None的键。
let disjoint_merge = IntMap.fold IntMap.add;;