PatriciaTree.MakeHeterogeneousMapSourceThis is the same as MAP, but with simple type key being replaced by type constructor 'a key and 'b value being replaced by ('a,'b) value.
The main changes from MAP are:
key is replaced by a type constructor 'k key. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyiter, polymap, polyunion, etc.)t) is still parameterized by an argument ('m t)value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.KeyValue constructor.module Key : HETEROGENEOUS_KEYmodule Value : HETEROGENEOUS_VALUEinclude BASE_MAP
with type 'a key = 'a Key.t
with type ('k, 'm) value = ('k, 'm) Value.tinclude NODE
with type 'a key = 'a Key.t
with type ('k, 'm) value = ('k, 'm) Value.tThe type of value, which depends on the type of the key and the type of the map.
The type of the map, which is parameterized by a type.
A singleton leaf, similar to BASE_MAP.singleton
A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.
When called, it assumes that:
tree0 nor tree1 should be empty.branching_bit should have a single bit setprefix should be normalized (bits below branching_bit set to zero)tree0 should have their to_int start by prefix followed by 0 at position branching_bit).tree1 should have their to_int start by prefix followed by 0 at position branching_bit).type 'map view = private | Empty : 'map viewCan happen only at the toplevel: there is no empty interior node.
*)| Branch : {} -> 'map viewSame constraints as branch:
branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).tree0 should have their to_int start by prefix followed by 0 at position branching_bit).tree1 should have their to_int start by prefix followed by 0 at position branching_bit).| Leaf : {} -> 'map viewA key -> value mapping.
*)This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.
Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair
unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.
unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.
is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.
find key map returns the value associated with key in map if present.
Same as find, but returns None for Not_found
mem key map returns true iff key is bound in map, O(log(n)) complexity.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
pop_unsigned_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = unsigned_min_binding m and m' = remove m key. Uses the unsigned order on KEY.to_int. O(log(n)) complexity.
pop_unsigned_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = unsigned_max_binding m and m' = remove m key. Uses the unsigned order on KEY.to_int. O(log(n)) complexity.
insert key f map modifies or insert an element of the map; f takes None if the value was not previously bound, and Some old where old is the previously bound value otherwise. The function preserves physical equality when possible. O(log(n)) complexity. Preserves physical equality if the new value is physically equal to the old.
val update :
'a key ->
(('a, 'map) value option -> ('a, 'map) value option) ->
'map t ->
'map tupdate key f map modifies, insert, or remove an element from the map; f takes None if the value was not previously bound, and Some old where old is the previously bound value otherwise. The function preserves physical equality when possible. It returns None if the element should be removed O(log(n)) complexity. Preserves physical equality if the new value is physically equal to the old.
Unconditionally adds a value in the map (independently from whether the old value existed). O(log(n)) complexity. Preserves physical equality if the new value is physically equal to the old.
split key map splits the map into:
map whose keys are smaller than keykey (if present)map whose keys are bigger than keyWhere the order is given by the unsigned order on KEY.to_int.
iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int
fold f m acc returns f.f key_n value_n (... (f.f key_1 value_1 acc)) where (key_1, value_1) ... (key_n, value_n) are the bindings of m, in the unsigned order on KEY.to_int.
fold_on_nonequal_inter f m1 m2 acc returns f.f key_n value1_n value2n (... (f.f key_1 value1_1 value2_1 acc)) where (key_1, value1_1, value2_1) ... (key_n, value1_n, value2_n) are the bindings that exist in both maps (m1 ∩ m2) whose values are physically different. Calls to f.f are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f.f key_n value1_n value2n (... (f.f key_1 value1_1 value2_1 acc)) where (key_1, value1_1, value2_1) ... (key_n, value1_n, value2_n) are the bindings that exists in either map (m1 ∪ m2) whose values are physically different. Calls to f.f are performed in the unsigned order of KEY.to_int.
filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int
for_all f m checks that f holds on all bindings of m. Short-circuiting.
In the following, the *no_share function allows taking arguments of different types (but cannot share subtrees of the map), while the default functions attempt to preserve and benefit from sharing the subtrees (using physical equality to detect sharing).
map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.
mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.
filter_map m f and filter_map_no_share m f remove the bindings (k,v) for which f.f k v is None, and replaces the bindings (k,v) for which f.f k v is Some v' by (k,v'). Bindings are examined in the unsigned order of KEY.to_int.
val pretty :
?pp_sep:(Format.formatter -> unit -> unit) ->
'map polypretty ->
Format.formatter ->
'map t ->
unitPretty-prints a map using the given formatter. pp_sep is called once between each binding, it defaults to Format.pp_print_cut. Bindings are printed in the unsigned order of KEY.to_int
val reflexive_same_domain_for_all2 :
('map, 'map) polysame_domain_for_all2 ->
'map t ->
'map t ->
boolreflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)(k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holdsAssumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.
It is useful to implement equality on maps:
# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2
{ f = fun _ v1 v2 -> MyValue.equal v1 v2}
m1 m2;;
val equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>val nonreflexive_same_domain_for_all2 :
('map1, 'map2) polysame_domain_for_all2 ->
'map1 t ->
'map2 t ->
boolnonreflexive_same_domain_for_all2 f m1 m2 is the same as reflexive_same_domain_for_all2, but doesn't assume f.f is reflexive. It thus calls f.f on every binding, in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.
val reflexive_subset_domain_for_all2 :
('map, 'map) polysame_domain_for_all2 ->
'map t ->
'map t ->
boolreflexive_subset_domain_for_all2 f m1 m2 is true if and only if
m1's domain is a subset of m2's. (all keys defined in m1 are also defined in m2)(k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holdsAssumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.
Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.
Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
nonidempotent_inter_no_share f map1 map2 is the same as idempotent_inter but doesn't preverse physical equality, doesn't assume f.f is idempotent, and can change the type of values. f.f is called on every shared binding. f.f is called in increasing unsigned order of keys. O(n) complexity
idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.
This is the same as Stdlib.Map.S.merge
to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int
to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int
add_seq s m adds all bindings of the sequence s to m in order.
of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept
of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept
to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.