diff --git a/.gitignore b/.gitignore
index 858bbb0..bba55a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,5 +12,7 @@ _site/
# Ignore folders generated by Bundler
.bundle/
-vendor/
-*~
\ No newline at end of file
+*~
+
+# VS Code editor config
+.vscode/
diff --git a/404.html b/404.html
new file mode 100644
index 0000000..425b4b4
--- /dev/null
+++ b/404.html
@@ -0,0 +1,12 @@
+---
+layout: default
+title: 404
+nav_exclude: true
+search_exclude: true
+permalink: /404.html
+---
+
+
Error 404
+
+
Page not found :(
+
The requested page could not be found.
diff --git a/Gemfile b/Gemfile
index f7e388c..1c48721 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,3 +5,4 @@ source "https://rubygems.org"
gem "just-the-docs", "0.8.2" # pinned to the current release
gem "github-pages"
gem "webrick"
+gem "jekyll-redirect-from"
diff --git a/Gemfile.lock b/Gemfile.lock
index f6dd1a5..b099051 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -270,6 +270,7 @@ PLATFORMS
DEPENDENCIES
github-pages
+ jekyll-redirect-from
just-the-docs (= 0.8.2)
webrick
diff --git a/_config.yml b/_config.yml
index 2e4d48e..a17ae6c 100644
--- a/_config.yml
+++ b/_config.yml
@@ -6,12 +6,31 @@ color_scheme: myscheme
url: https://codex-semantics-library.github.io
aux_links:
- Repository: https://github.com/codex-semantics-library/codex
+ ' Repository': https://github.com/codex-semantics-library/codex
logo: "/assets/codex.png"
-nav_external_links:
- - title: Patricia Tree Library
- url: patricia-tree
- hide_icon: true # set to true to hide the external link icon - defaults to false
- opens_in_new_tab: false # set to true to open this link in a new tab - defaults to false
+callouts:
+ warning:
+ title: Warning
+ color: red
+ note:
+ color: blue
+
+exclude: [
+ Makefile,
+ README.md,
+ .sass-cache/,
+ .jekyll-cache/,
+ gemfiles/,
+ Gemfile,
+ Gemfile.lock
+ node_modules/,
+ vendor/bundle/,
+ vendor/cache/,
+ vendor/gems/,
+ vendor/ruby/,
+ ]
+
+plugins:
+ - jekyll-redirect-from
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..cf3033d
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HashconsedNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..5cc192d
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HashconsedNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values for a hash-consed maps.
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/index.html.json
new file mode 100644
index 0000000..36e0d38
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HashconsedNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HashconsedNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Gives a unique number to each node like NodeWithId, but also performs hash-consing. So two maps with the same bindings will always be physically equal. See Hash-consed maps and sets for more details on this.
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
Using a single HashconsedNode in multiple MakeCustomMap functors will result in all those maps being hash-consed together (stored in the same hash-table, same numbering system).
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.
Returns a unique number for each map, the hash-consed identifier of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Maps with the same identifier are also physically equal: to_int m1 = to_int m2 implies m1 == m2.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HashconsedSetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HashconsedSetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..483a415
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HashconsedSetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HashconsedSetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HashconsedSetNode/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HashconsedSetNode/index.html.json
new file mode 100644
index 0000000..b13985e
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HashconsedSetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HashconsedSetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
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.
Returns a unique number for each map, the hash-consed identifier of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Maps with the same identifier are also physically equal: to_int m1 = to_int m2 implies m1 == m2.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HashedValue/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HashedValue/index.html.json
new file mode 100644
index 0000000..0d4404a
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HashedValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HashedValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Generic implementation of HASHED_VALUE. Uses Hashtbl.hash for hashing and physical equality for equality. Note that this may lead to maps of different types having the same identifier (MakeHashconsedMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.
","content":"
type'a t = 'a
The type of values for a hash-consed maps.
Unlike VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : t1 t and b : t2 t yield polyeq a b = true, then let a' : t2 t = Obj.magic a and let b' : t1 t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type 'a t which doesn't depend on 'a, in which case casting form 'a t to 'b t is always safe:
type _ t = foo\u000Alet cast : type a b. a t -> b t = fun x -> x\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type _ t =\u000A | T_Int : int -> int t\u000A | T_Bool : bool -> bool t\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HashedValue. Note however that using this function can lead to identifiers no longer being unique across types. They will still be unique and behave as expected within a certain type, but since some values of different types can physically equal, we may have identifer clashes:
# 97 == Obj.magic 'a';;\u000A- : bool = true
module HMap = MakeHashconsedMap(struct\u000A type t = int\u000A let to_int x = x\u000Aend)(HashedValue)()
This issue does not happen with the two previous variants, since they both only return true on the same types.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HeterogeneousHashedValue/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HeterogeneousHashedValue/index.html.json
new file mode 100644
index 0000000..eadfd85
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HeterogeneousHashedValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HeterogeneousHashedValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/HomogeneousValue/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/HomogeneousValue/index.html.json
new file mode 100644
index 0000000..c140390
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/HomogeneousValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HomogeneousValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Default implementation of HETEROGENEOUS_VALUE, to use when the type of the value in a heterogeneous map does not depend on the type of the key, only on the type of the map.
","content":"
type('a, 'map) t = 'map
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..05d72de
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/index.html.json
new file mode 100644
index 0000000..c130173
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..4161087
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..66c4792
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-3-Node/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-3-Node/index.html.json
new file mode 100644
index 0000000..eef5e35
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/argument-3-Node/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Node","href":"#","kind":"argument-3"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/index.html.json
new file mode 100644
index 0000000..9838ac2
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
The type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..ab789c3
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..83c7123
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/index.html.json
new file mode 100644
index 0000000..37610a6
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
","content":"
includeBASE_MAP\u000A withtype'a key = 'aelt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNODE.t
includeNODE\u000A withtype'a key = 'aelt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNODE.t
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..eba4b68
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/argument-2-NODE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/argument-2-NODE/index.html.json
new file mode 100644
index 0000000..d011bdc
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/argument-2-NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"NODE","href":"#","kind":"argument-2"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/index.html.json
new file mode 100644
index 0000000..691d69f
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomHeterogeneousSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..daa22f4
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..5cd68c3
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/index.html.json
new file mode 100644
index 0000000..74c8c9a
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..6e4b7ea
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/WithForeign/index.html.json
new file mode 100644
index 0000000..d19b7f1
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..81c2f86
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..1212b48
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'a t
The type of values. A 'map map maps key to 'map value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-3-Node/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-3-Node/index.html.json
new file mode 100644
index 0000000..1f85d30
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/argument-3-Node/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"Node","href":"#","kind":"argument-3"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/index.html.json
new file mode 100644
index 0000000..ced581e
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
Create a homogeneous map with a custom NODE. Also allows customizing the map values
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..cf20864
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..b997d8b
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/index.html.json
new file mode 100644
index 0000000..d0749c5
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
","content":"
includeBASE_MAP\u000A withtype_ key = elt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNode.t
includeNODE\u000A withtype_ key = elt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNode.t
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..5db67e2
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/argument-2-Node/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/argument-2-Node/index.html.json
new file mode 100644
index 0000000..a2fde40
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/argument-2-Node/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../index.html","kind":"module"},{"name":"Node","href":"#","kind":"argument-2"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/index.html.json
new file mode 100644
index 0000000..42f0923
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeCustomSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..72c4f79
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/index.html.json
new file mode 100644
index 0000000..90a863a
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..c98aec5
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..c8b2401
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values for a hash-consed maps.
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/index.html.json
new file mode 100644
index 0000000..0686b9b
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..ac12319
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..26e53ac
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/index.html.json
new file mode 100644
index 0000000..134af47
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..4d75f46
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/index.html.json
new file mode 100644
index 0000000..9217619
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedHeterogeneousSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..68ed332
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..26e7fce
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/index.html.json
new file mode 100644
index 0000000..1ad5be0
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..2f34243
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/WithForeign/index.html.json
new file mode 100644
index 0000000..508c78f
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..a66777e
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..2fea073
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'a t
The type of values for a hash-consed maps.
Unlike VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : t1 t and b : t2 t yield polyeq a b = true, then let a' : t2 t = Obj.magic a and let b' : t1 t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type 'a t which doesn't depend on 'a, in which case casting form 'a t to 'b t is always safe:
type _ t = foo\u000Alet cast : type a b. a t -> b t = fun x -> x\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type _ t =\u000A | T_Int : int -> int t\u000A | T_Bool : bool -> bool t\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HashedValue. Note however that using this function can lead to identifiers no longer being unique across types. They will still be unique and behave as expected within a certain type, but since some values of different types can physically equal, we may have identifer clashes:
# 97 == Obj.magic 'a';;\u000A- : bool = true
module HMap = MakeHashconsedMap(struct\u000A type t = int\u000A let to_int x = x\u000Aend)(HashedValue)()
This issue does not happen with the two previous variants, since they both only return true on the same types.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/index.html.json
new file mode 100644
index 0000000..2d727f2
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Hash-consed version of MAP. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed maps.
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..cbbd622
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..390e589
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/index.html.json
new file mode 100644
index 0000000..91cb93f
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..9abe574
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/index.html.json
new file mode 100644
index 0000000..963a5c8
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHashconsedSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Hash-consed version of SET. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed sets.
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..dea897b
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json
new file mode 100644
index 0000000..b4afd2b
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..c9ce4bc
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..256fe90
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/index.html.json
new file mode 100644
index 0000000..3502e25
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..746ee9a
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..a508c32
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json
new file mode 100644
index 0000000..4863ef0
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..ab4a19b
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/index.html.json
new file mode 100644
index 0000000..affd439
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeHeterogeneousSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..6691db6
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..473abf9
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/index.html.json
new file mode 100644
index 0000000..c652939
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..fe68775
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/WithForeign/index.html.json
new file mode 100644
index 0000000..78dd5d9
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..785b52f
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/index.html.json
new file mode 100644
index 0000000..f54336a
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"","content":"
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..1d48c09
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..c56e455
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/index.html.json
new file mode 100644
index 0000000..7e9bfef
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..d5af357
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/MakeSet/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/index.html.json
new file mode 100644
index 0000000..820b10a
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/MakeSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"","content":"
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/argument-1-Key/index.html.json
new file mode 100644
index 0000000..c11770f
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"NodeWithId","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/argument-2-Value/index.html.json
new file mode 100644
index 0000000..3bfcde5
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"NodeWithId","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/index.html.json
new file mode 100644
index 0000000..2dc298d
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/NodeWithId/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NodeWithId","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hash-tables.
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.
This is not hash-consing. Equal nodes created separately will have different identifiers. On the flip side, nodes with equal identifiers will always be physically equal.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/SetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/SetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..ebc947e
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/SetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/SetNode/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/SetNode/index.html.json
new file mode 100644
index 0000000..01353d4
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/SetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
An optimized representation for sets, i.e. maps to unit: we do not store a reference to unit (note that you can further optimize when you know the representation of the key). This is the node used in MakeHeterogeneousSet and MakeSet.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..b3e4977
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SimpleNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..992e324
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SimpleNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/index.html.json
new file mode 100644
index 0000000..e6ac250
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/SimpleNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SimpleNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/Value/index.html.json
new file mode 100644
index 0000000..f99755c
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
The type of values. A 'map map maps key to 'map value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/WeakNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/WeakNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..2ce648d
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/WeakNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/WeakNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/WeakNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..b20af62
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/WeakNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/WeakNode/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/WeakNode/index.html.json
new file mode 100644
index 0000000..1a7fbc5
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/WeakNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WeakNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
NODE used to implement weak key hashes (the key-binding pair is an Ephemeron, the reference to the key is weak, and if the key is garbage collected, the binding disappears from the map
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..9a3e167
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakSetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/WeakSetNode/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/WeakSetNode/index.html.json
new file mode 100644
index 0000000..27e44bd
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/WeakSetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WeakSetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
Both a WeakNode and a SetNode, useful to implement Weak sets.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/WrappedHomogeneousValue/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/WrappedHomogeneousValue/index.html.json
new file mode 100644
index 0000000..39b5d0b
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/WrappedHomogeneousValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WrappedHomogeneousValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Same as HomogeneousValue, but uses a wrapper (unboxed) type instead of direct equality. This avoids a problem in the typechecker with overly eager simplification of aliases. More info on the OCaml discourse post.
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/index.html.json
new file mode 100644
index 0000000..f7036c8
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../index.html","kind":"page"},{"name":"PatriciaTree","href":"#","kind":"module"}],"toc":[{"title":"Nodes","href":"#nodes","children":[]},{"title":"Map signatures","href":"#map-signatures","children":[{"title":"Base map","href":"#base-map","children":[]},{"title":"Heterogeneous maps and sets","href":"#heterogeneous-maps-and-sets","children":[]},{"title":"Homogeneous maps and sets","href":"#homogeneous-maps-and-sets","children":[]}]},{"title":"Keys","href":"#keys","children":[]},{"title":"Values","href":"#values","children":[]},{"title":"Functors","href":"#functors","children":[{"title":"Homogeneous maps and sets","href":"#homogeneous-maps-and-sets_2","children":[]},{"title":"Heterogeneous maps and sets","href":"#heterogeneous-maps-and-sets_2","children":[]},{"title":"Maps and sets with custom nodes","href":"#maps-and-sets-with-custom-nodes","children":[]},{"title":"Hash-consed maps and sets","href":"#hash_consed","children":[]}]},{"title":"Some implementations of NODE","href":"#node_impl","children":[{"title":"Basic nodes","href":"#basic-nodes","children":[]},{"title":"Weak nodes","href":"#weak-nodes","children":[]},{"title":"Hashconsed nodes","href":"#hashconsed-nodes","children":[]}]}],"source_anchor":null,"preamble":"
Association maps from key to values, and sets, implemented with Patricia Trees, allowing fast merge operations by making use of physical equality between subtrees; and custom implementation of tree nodes (allowing normal maps, hash-consed maps, weak key or value maps, sets, custom maps, etc.)
This is similar to OCaml's Map, except that:
The required signature for keys is different, in that we require each key to be mapped to a unique integer identifier.
The implementation uses Patricia Tree, as described in Okasaki and Gill's 1998 paper Fast mergeable integer maps, i.e. it is a space-efficient prefix trie over the big-endian representation of the key's integer identifier.
Example of a 5-bit patricia tree containing five numbers: 0 0b0000, 1 0b0001, 5 0b0101 and 7 0b0111 and -8 0b1111:
The main benefit of Patricia Tree is that their representation is stable (contrary to maps, inserting nodes in any order will return the same shape), which allows different versions of a map to share more subtrees in memory, and the operations over two maps to benefit from this sharing. The functions in this library attempt to maximally preserve sharing and benefit from sharing, allowing very important improvements in complexity and running time when combining maps or sets is a frequent operation.
Finally, the implementation is more customizable, allowing notably (key,value) pairs or different types to be in the same map, or to choose the memory representation of the nodes of the tree.
Some operations like pop_unsigned_minimum and pop_unsigned_maximum make our Set suitable as priority queue (but remember that each element in the queue must map to a distinct integer, and that using the unsigned order means elements with negative priority are seen as greater than elements with positive ones).
","content":"
Note on complexity: in the following, n represents the size of the map when there is one (and |map1| is the number of elements in map1). The term log(n) correspond to the maximum height of the tree, which is log(n) if we assume an even distribution of numbers in the map (e.g. random distribution, or integers chosen contiguously using a counter). The worst-case height is O(min(n,64)) which is actually constant, but not really informative; log(n) corresponds to the real complexity in usual distributions.
val unsigned_lt : int ->int -> bool
All integers comparisons in this library are done according to their unsigned representation. This is the same as signed comparison for same sign integers, but all negative integers are greater than the positives. This means -1 is the greatest possible number, and 0 is the smallest.
Hash-consed nodes also associate a unique number to each node, Unlike NODE_WITH_ID, they also check before instanciating the node whether a similar node already exists. This results in slightly slower constructors (they perform an extra hash-table lookup), but allows for constant time equality and comparison.
Base map signature: a generic 'b map storing bindings of 'a key to ('a,'b) values. All maps and set are a variation of this type, sometimes with a simplified interface.
Heterogeneous maps and sets
Maps and sets with generic keys 'a key and values ('a,'b) value
Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.
type(_, 'b) snd =
| Sndof'b
The typechecker struggles with forall quantification on values if they don't depend on the first parameter, this wrapping allows our code to pass typechecking by forbidding overly eager simplification. Since the type is unboxed, it doesn't introduce any performance overhead.
The signature for maps with a single type for keys and values, a 'a map binds key to 'a value. This is slightly more generic than MAP, which just binds to 'a. It is used for maps that need to restrict their value type, namely Hash-consed maps and sets.
To have heterogeneous keys, we must define a polymorphic equality function. Like in the homogeneous case, it should have the requirement that (to_int a) = (to_int b) ==> polyeq a b = Eq.
Module type used for specifying custom homogeneous value types in MakeCustomMap. For most purposes, use the provided Value implementation. It sets 'a t = 'a, which is the desired effect (maps can map to any value). This is the case in MakeMap. However, for maps like Hash-consed maps and sets, it can be useful to restrict the type of values in order to implement hash and polyeq functions on values. See the HASHED_VALUE module type for more details.
The module type of values, which can be heterogeneous. This can be used to specify how the type of the value depends on that of the key. If the value doesn't depend on the key type, you can use the provided default implementations HomogeneousValue and WrappedHomogeneousValue.
Default implementation of HETEROGENEOUS_VALUE, to use when the type of the value in a heterogeneous map does not depend on the type of the key, only on the type of the map.
Same as HomogeneousValue, but uses a wrapper (unboxed) type instead of direct equality. This avoids a problem in the typechecker with overly eager simplification of aliases. More info on the OCaml discourse post.
Generic implementation of HASHED_VALUE. Uses Hashtbl.hash for hashing and physical equality for equality. Note that this may lead to maps of different types having the same identifier (MakeHashconsedMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.
Heterogeneous maps are 'map map, which store bindings of 'key key to ('key, 'map) value, where 'key key is a GADT, as we must be able to compare keys of different types together.
Similarly, heterogeneous sets store sets of 'key key.
This 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.
Maps and sets with custom nodes
We can also customize the representation and creation of nodes, to gain space or time.
Possibitities include having weak key and/or values, hash-consing, giving unique number to nodes or keeping them in sync with the disk, lazy evaluation and/or caching, adding size information for constant time cardinal functions, etc.
Hash-consed maps and sets uniquely number each of their nodes. Upon creation, they check whether a similar node has been created before, if so they return it, else they return a new node with a new number. With this unique numbering:
equal and compare become constant time operations;
two maps with the same bindings (where keys are compared by KEY.to_int and values by HASHED_VALUE.polyeq) will always be physically equal;
constructors are slightly slower, as they now require a hash-table lookup;
memory usage is increased: nodes store their tags inside themselves, and a global hash-table of all built nodes must be maintained;
hash-consed maps assume their values are immutable;
WARNING: when using physical equality as HASHED_VALUE.polyeq, some maps of different types may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details. Note that this is the case in the default implementations HashedValue and HeterogeneousHashedValue.
All hash-consing functors are generative, since each functor call will create a new hash-table to store the created nodes. Calling a functor twice with same arguments will lead to two numbering systems for identifiers, and thus the types should not be considered compatible.
Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hash-tables.
moduleSetNode\u000A (Key : sig ... end) : \u000A NODEwithtype'a key = 'aKey.tandtype('key, 'map) value = unit
An optimized representation for sets, i.e. maps to unit: we do not store a reference to unit (note that you can further optimize when you know the representation of the key). This is the node used in MakeHeterogeneousSet and MakeSet.
NODE used to implement weak key hashes (the key-binding pair is an Ephemeron, the reference to the key is weak, and if the key is garbage collected, the binding disappears from the map
Gives a unique number to each node like NodeWithId, but also performs hash-consing. So two maps with the same bindings will always be physically equal. See Hash-consed maps and sets for more details on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-BASE_MAP/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-BASE_MAP/index.html.json
new file mode 100644
index 0000000..6b1c424
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-BASE_MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"BASE_MAP","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
Base map signature: a generic 'b map storing bindings of 'a key to ('a,'b) values. All maps and set are a variation of this type, sometimes with a simplified interface.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HASHED_VALUE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HASHED_VALUE/index.html.json
new file mode 100644
index 0000000..0e4fe72
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HASHED_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HASHED_VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
This is the parameter type for homogeneous maps, used in MakeHashconsedMap. A default implementation is provided in HashedValue, using Hashtbl.hash as hash function and physical equality as polyeq.
since 0.10.0
","content":"
type'a t
The type of values for a hash-consed maps.
Unlike VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : t1 t and b : t2 t yield polyeq a b = true, then let a' : t2 t = Obj.magic a and let b' : t1 t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type 'a t which doesn't depend on 'a, in which case casting form 'a t to 'b t is always safe:
type _ t = foo\u000Alet cast : type a b. a t -> b t = fun x -> x\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type _ t =\u000A | T_Int : int -> int t\u000A | T_Bool : bool -> bool t\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HashedValue. Note however that using this function can lead to identifiers no longer being unique across types. They will still be unique and behave as expected within a certain type, but since some values of different types can physically equal, we may have identifer clashes:
# 97 == Obj.magic 'a';;\u000A- : bool = true
module HMap = MakeHashconsedMap(struct\u000A type t = int\u000A let to_int x = x\u000Aend)(HashedValue)()
This issue does not happen with the two previous variants, since they both only return true on the same types.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HASH_CONSED_NODE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HASH_CONSED_NODE/index.html.json
new file mode 100644
index 0000000..7f56e40
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HASH_CONSED_NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HASH_CONSED_NODE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Hash-consed nodes also associate a unique number to each node, Unlike NODE_WITH_ID, they also check before instanciating the node whether a similar node already exists. This results in slightly slower constructors (they perform an extra hash-table lookup), but allows for constant time equality and comparison.
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.
Returns a unique number for each map, the hash-consed identifier of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Maps with the same identifier are also physically equal: to_int m1 = to_int m2 implies m1 == m2.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_HASHED_VALUE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_HASHED_VALUE/index.html.json
new file mode 100644
index 0000000..b84f0f3
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_HASHED_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_HASHED_VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json
new file mode 100644
index 0000000..a70cd50
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_KEY","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The signature of heterogeneous keys.
","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..e6baa70
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json
new file mode 100644
index 0000000..c924d79
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json
new file mode 100644
index 0000000..2cadb60
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..099d864
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..8490d5f
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json
new file mode 100644
index 0000000..9b56a13
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json
new file mode 100644
index 0000000..8ec39ef
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_VALUE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_VALUE/index.html.json
new file mode 100644
index 0000000..adf3cbf
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-HETEROGENEOUS_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The module type of values, which can be heterogeneous. This can be used to specify how the type of the value depends on that of the key. If the value doesn't depend on the key type, you can use the provided default implementations HomogeneousValue and WrappedHomogeneousValue.
","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-KEY/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-KEY/index.html.json
new file mode 100644
index 0000000..fbe1232
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-KEY/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"KEY","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The signature of homogeneous keys (non-generic, unparameterized keys).
","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..020e47b
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MAP","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..e26b289
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/index.html.json
new file mode 100644
index 0000000..b641781
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..7be3f02
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/WithForeign/index.html.json
new file mode 100644
index 0000000..5f4a8a5
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/index.html.json
new file mode 100644
index 0000000..4220bd3
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MAP","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
The signature for maps with a single type for keys and values, a 'a map binds key to 'a. Most of this interface should be shared with Stdlib.Map.S.
","content":"
type key
The type of keys.
type'a t
A map from key to values of type 'a value.
type'a value = 'a
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..8aa4b85
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..5bbd11a
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/index.html.json
new file mode 100644
index 0000000..017cabd
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..a8d9ac1
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/index.html.json
new file mode 100644
index 0000000..7b880ec
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/index.html.json
new file mode 100644
index 0000000..66891b2
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-MAP_WITH_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
The signature for maps with a single type for keys and values, a 'a map binds key to 'a value. This is slightly more generic than MAP, which just binds to 'a. It is used for maps that need to restrict their value type, namely Hash-consed maps and sets.
","content":"
type key
The type of keys.
type'a t
A map from key to values of type 'a value.
type'a value
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-NODE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-NODE/index.html.json
new file mode 100644
index 0000000..722b6fd
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NODE","href":"#","kind":"module-type"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
This module explains how a node is stored in memory, with functions to create and view nodes.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
","content":"
Types
type'key key
The type of keys.
type('key, 'map) value
The type of value, which depends on the type of the key and the type of the map.
type'map t
The type of the map, which is parameterized by a type.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-NODE_WITH_ID/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-NODE_WITH_ID/index.html.json
new file mode 100644
index 0000000..4c29d5d
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-NODE_WITH_ID/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NODE_WITH_ID","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Associate a unique number to each node, so they can be used as keys in sets or maps.
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.
This is not hash-consing. Equal nodes created separately will have different identifiers. On the flip side, nodes with equal identifiers will always be physically equal.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..de07e5f
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"SET","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..6384bcd
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"SET","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/index.html.json
new file mode 100644
index 0000000..c7588ea
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SET","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/index.html.json
new file mode 100644
index 0000000..1ae34ce
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-SET/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SET","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/PatriciaTree/module-type-VALUE/index.html.json b/_data/api/patricia-tree/main/PatriciaTree/module-type-VALUE/index.html.json
new file mode 100644
index 0000000..afd42e1
--- /dev/null
+++ b/_data/api/patricia-tree/main/PatriciaTree/module-type-VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Module type used for specifying custom homogeneous value types in MakeCustomMap. For most purposes, use the provided Value implementation. It sets 'a t = 'a, which is the desired effect (maps can map to any value). This is the case in MakeMap. However, for maps like Hash-consed maps and sets, it can be useful to restrict the type of values in order to implement hash and polyeq functions on values. See the HASHED_VALUE module type for more details.
since 0.10.0
","content":"
type'a t
The type of values. A 'map map maps key to 'map value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/main/index.html.json b/_data/api/patricia-tree/main/index.html.json
new file mode 100644
index 0000000..a75495b
--- /dev/null
+++ b/_data/api/patricia-tree/main/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"#","kind":"page"},{"name":"index","href":"#","kind":"leaf-page"}],"toc":[{"title":"Installation","href":"#installation","children":[]},{"title":"Features","href":"#features","children":[]},{"title":"Quick overview","href":"#quick-overview","children":[{"title":"Functors","href":"#functors","children":[]},{"title":"Interfaces","href":"#interfaces","children":[]}]},{"title":"Examples","href":"#examples","children":[{"title":"Homogeneous map","href":"#homogeneous-map","children":[]},{"title":"Heterogeneous map","href":"#heterogeneous-map","children":[]}]},{"title":"Release status","href":"#release-status","children":[]},{"title":"Known issues","href":"#known-issues","children":[]},{"title":"Comparison to other OCaml libraries","href":"#comparison-to-other-ocaml-libraries","children":[{"title":"ptmap and ptset","href":"#ptmap-and-ptset","children":[]},{"title":"dmap","href":"#dmap","children":[]}]},{"title":"Contributions and bug reports","href":"#contributions-and-bug-reports","children":[]}],"source_anchor":null,"preamble":"
Package patricia-tree
This library contains a single module: PatriciaTree.
This is version 0.10.0 of the library. It is known to work with OCaml versions ranging from 4.14 to 5.2.
This is an OCaml library that implements sets and maps as Patricia Trees, as described in Okasaki and Gill's 1998 paper Fast mergeable integer maps. It is a space-efficient prefix trie over the big-endian representation of the key's integer identifier.
The source code of this library is available on Github under an LGPL-2.1 license.
Similar to OCaml's Map and Set, using the same function names when possible and the same convention for order of arguments. This should allow switching to and from Patricia Tree with minimal effort.
The functor parameters (KEY module) requires an injective to_int : t -> int function instead of a compare function. KEY.to_int should be fast, and injective. This works well with hash-consed types.
The Patricia Tree representation is stable, contrary to maps, inserting nodes in any order will return the same shape. This allows different versions of a map to share more subtrees in memory, and the operations over two maps to benefit from this sharing. The functions in this library attempt to maximally preserve sharing and benefit from sharing, allowing very important improvements in complexity and running time when combining maps or sets is a frequent operation.
To do so, these functions often have extra requirements on their argument (e.g. inter f m1 m2 can be optimized by not inspecting common subtrees when f is idempotent). To avoid accidental errors, they are renamed (e.g. to idempotent_inter for the efficient version and nonidempotent_inter_no_share for the general one)
Since our Patricia Tree use big-endian order on keys, the maps and sets are sorted in increasing unsigned order of keys. This means negative keys are sorted above positive keys, with -1 being the largest possible key, and 0 the smallest. This also avoids a bug in Okasaki's paper discussed in QuickChecking Patricia Trees by Jan Mitgaard.
It also affects functions like unsigned_min_binding and pop_unsigned_minimum. They will return the smallest positive integer of both positive and negative keys are present; and not the smallest negative, as one might expect.
Supports generic maps and sets: a 'm map that maps 'k key to ('k, 'm) value. This is especially useful when using GADTs for the type of keys. This is also sometimes called a dependent map.
Allows easy and fast operations across different types of maps and set which have the same type of keys (e.g. an intersection between a map and a set).
Multiple choices for internal representation (NODE), which allows for efficient storage (no need to store a value for sets), or using weak nodes only (values removed from the tree if no other pointer to it exists). This system can also be extended to store size information in nodes if needed.
Exposes a common interface (PatriciaTree.NODE.view) to allow users to write their own pattern matching on the tree structure without depending on the NODE being used.
Additionally, hashconsed versions of heterogeneous/homogeneous maps/sets are available. These provide constant time equality and comparison, and ensure maps/set with the same constants are always physically equal. It comes at the cost of a constant overhead in memory usage (at worst, as hash-consing may allow memory gains) and constant time overhead when calling constructors.
Quick overview
Functors
This library contains a single module, PatriciaTree. The functors used to build maps and sets are the following:
For homogeneous (non-generic) maps and sets: MakeMap and MakeSet. These are similar to the standard library's maps and sets.
module MakeMap(Key: KEY) : MAP with type key = Key.t\u000Amodule MakeSet(Key: KEY) : SET with type elt = Key.t
module MakeHeterogeneousMap(Key: HETEROGENEOUS_KEY)(Value: HETEROGENEOUS_VALUE) :\u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k,'m) value = ('k,'m) Value.t\u000Amodule MakeHeterogeneousSet(Key: HETEROGENEOUS_KEY) : HETEROGENEOUS_SET\u000A with type 'a elt = 'a Key.t
equal and compare become constant time operations;
two maps with the same bindings (where keys are compared by KEY.to_int and values by HASHED_VALUE.polyeq) will always be physically equal;
functions that benefit from sharing will see improved performance;
constructors are slightly slower, as they now require a hash-table lookup;
memory usage is increased: nodes store their tags inside themselves, and a global hash-table of all built nodes must be maintained;
hash-consed maps assume their values are immutable;
WARNING: when using physical equality as HASHED_VALUE.polyeq, some maps of different types may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details. Note that this is the case in the default implementations HashedValue and HeterogeneousHashedValue.
All hash-consing functors are generative, since each functor call will create a new hash-table to store the created nodes. Calling a functor twice with same arguments will lead to two numbering systems for identifiers, and thus the types should not be considered compatible.
Interfaces
Here is a brief overview of the various module types of our library:
BASE_MAP: the underlying module type of all our trees (maps end sets). It represents a 'b map binding 'a key to ('a,'b) value, as well as all functions needed to manipulate them.
It can be accessed from any of the more specific maps types, thus providing a unified representation, useful for cross map operations. However, for practical purposes, it is often best to use the more specific interfaces:
MAP for homogeneous maps, this interface is close to Stdlib.Map.S.
HETEROGENEOUS_SET for heterogeneous sets (sets of 'a elt). These are just maps to unit, but with a custom node representation to avoid storing unit in nodes.
SET for homogeneous sets, this interface is close to Stdlib.Set.S.
The parameter of our functor are either KEY or HETEROGENEOUS_KEY. These just consist of a type, a (polymorphic) equality function, and an injective to_int coercion.
The heterogeneous map functor also has a HETEROGENEOUS_VALUE parameter to specify the ('a, 'b) value type.
The internal representations of our tree can be customized to use different internal NODE. Each node come with its own private constructors and destructors, as well as a cast to a uniform NODE.view type used for pattern matching.
HashconsedNode: performs hash-consing (it also stores a unique identifier, but checks when building a new node whether a node with similar content already exists);
module IntKey : PatriciaTree.KEY with type t = int = struct\u000A type t = int\u000A let to_int x = x\u000Aend
Use it to instanciate the map/set functors:
module IMap : PatriciaTree.MAP with type key = int = PatriciaTree.MakeMap(IntKey);;\u000Amodule ISet : PatriciaTree.SET with type elt = int = PatriciaTree.MakeSet(IntKey);;
You can now use it as you would any other map:
# let map =\u000A IMap.empty |>\u000A IMap.add 1 "hello" |>\u000A IMap.add 2 "world" |>\u000A IMap.add 3 "how do you do?";;\u000Aval map : string IMap.t = <abstr>
(We also have of_list and of_seq functions for quick initialization)
The strength of Patricia Tree is the speedup of operations on multiple maps with common subtrees. For example, in the following, the idempotent_inter_filter function will skip recursive calls to physically equal subtrees (kept as-is in the intersection). This allows faster than O(n) intersections.
Physical equality is preserved as much as possible, although some intersections may need to build new nodes and won't be fully physically equal, they will still share some subtrees.
# let str = IMap.find 1 map;;\u000Aval str : string = "hello"\u000A# IMap.add 1 str map == map (* already present *);;\u000A- : bool = true\u000A# IMap.add 1 "hello" map == map\u000A (* new string copy isn't physically equal to the old one *);;\u000A- : bool = false
Note that physical equality isn't preserved when creating new copies of values (the newly created string "hello" isn't physically equal to str). It can also fail when maps have the same bindings but were created differently:
For example, you can only keep the bindings of map whose keys are in a given set:
# let set = ISet.of_list [1; 3];;\u000Aval set : ISet.t = <abstr>\u000A# let restricted_map = CrossOperations.nonidempotent_inter\u000A { f = fun _key value () -> value } map set;;\u000Aval restricted_map : string IMap.t = <abstr>\u000A# IMap.to_list map;;\u000A- : (int * string) list = [(1, "hello"); (2, "world"); (3, "how do you do?")]\u000A# IMap.to_list restricted_map;;\u000A- : (int * string) list = [(1, "hello"); (3, "how do you do?")]
Heterogeneous map
Heterogeneous maps work very similarly to homogeneous ones, but come with extra liberty of having a generic type as a key.
Here is a GADT example to use for our keys: a small typed expression language.
type 'a expr =\u000A | G_Const_Int : int -> int expr\u000A | G_Const_Bool : bool -> bool expr\u000A | G_Addition : int expr * int expr -> int expr\u000A | G_Equal : 'a expr * 'a expr -> bool expr
We can create our HETEROGENEOUS_KEY functor parameter using this type has follows:
module Expr : PatriciaTree.HETEROGENEOUS_KEY with type 'a t = 'a expr = struct\u000A type 'a t = 'a expr\u000A\u000A (** Injective, so long as expressions are small enough\u000A (encodes the constructor discriminant in two lowest bits).\u000A Ideally, use a hash-consed type, to_int needs to be fast *)\u000A let rec to_int : type a. a expr -> int = function\u000A | G_Const_Int i -> 0 + 4*i\u000A | G_Const_Bool b -> 1 + 4*(if b then 1 else 0)\u000A | G_Addition(l,r) -> 2 + 4*(to_int l mod 10000 + 10000*(to_int r))\u000A | G_Equal(l,r) -> 3 + 4*(to_int l mod 10000 + 10000*(to_int r))\u000A\u000A (** Full polymorphic equality *)\u000A let rec polyeq : type a b. a expr -> b expr -> (a, b) PatriciaTree.cmp =\u000A fun l r -> match l, r with\u000A | G_Const_Int l, G_Const_Int r -> if l = r then Eq else Diff\u000A | G_Const_Bool l, G_Const_Bool r -> if l = r then Eq else Diff\u000A | G_Addition(ll, lr), G_Addition(rl, rr) -> (\u000A match polyeq ll rl with\u000A | Eq -> polyeq lr rr\u000A | Diff -> Diff)\u000A | G_Equal(ll, lr), G_Equal(rl, rr) -> (\u000A match polyeq ll rl with\u000A | Eq -> (match polyeq lr rr with Eq -> Eq | Diff -> Diff) (* Match required by typechecker *)\u000A | Diff -> Diff)\u000A | _ -> Diff\u000Aend
We can now instanciate our map functor. Note that in the heterogeneous case, we must also specify the value type (second functor argument) and how it depends on the key type (first parameter) and the map type (second parameter). Here the value only depends on the type of the key, not that of the map
module EMap = PatriciaTree.MakeHeterogeneousMap(Expr)(struct type ('a, _) t = 'a end)
You can now use this as you would any other dependent map:
Physical equality preservation allows fast operations on multiple maps with common ancestors. In the heterogeneous case, these functions are a bit more complex since OCaml requires that first-order polymorphic functions be wrapped in records:
# let map2 = EMap.idempotent_inter_filter\u000A { f = fun _key _l _r -> None } (* polymorphic 1rst order functions are wrapped in records *)\u000A (EMap.add (G_Const_Int 0) 8 map)\u000A (EMap.add (G_Const_Int 0) 9 map)\u000Aval map2 : unit EMap.t = <abstr>
Even though map and map2 have the same elements, they may not always be physically equal:
# map == map2;;\u000A- : bool = false
This is because they were created through different processes. They will still share subtrees. If you want to maintain full physical equality (and thus get cheap equality test between maps), use the provided hash-consed maps and sets.
Release status
This should be close to a stable release. It is already being used as part of a larger project successfully, and this usage as helped us mature the interface. As is, we believe the project is usable, and we don't anticipate any major change before 1.0.0. We didn't commit to a stable release straight away as we would like a bit more time using this library before doing so.
Known issues
There is a bug in the OCaml typechecker which prevents us from directly defining non-generic maps as instances of generic maps. To avoid this, non-generic maps use a separate value type ('a, 'b) snd (instead of just using 'b)
type (_, 'b) snd = Snd of 'b [@@unboxed]
It should not incur any extra performance cost as it is unboxed, but can appear when manipulating non-generic maps.
There are other implementations of Patricia Tree in OCaml, namely ptmap and ptset, both by J.C. Filliatre. These are smaller and closer to OCaml's built-in Map and Set, however:
Our library allows using any type key that comes with an injective to_int function, instead of requiring key = int.
We support generic types for keys/elements.
We support operations between sets and maps of different types.
We use a big-endian representation, allowing easy access to min/max elements of maps and trees.
Our interface and implementation tries to maximize the sharing between different versions of the tree, and to benefit from this memory sharing. Theirs do not.
These libraries work with older version of OCaml (>= 4.05 I believe), whereas ours requires OCaml >= 4.14 (for the new interface of Ephemeron used in WeakNode).
dmap
Additionally, there is a dependent map library: dmap, which gave us the idea of making our PatriciaTree dependent. It allows creating type safe dependent maps similar to our heterogeneous maps. However, its maps aren't Patricia trees. They are binary trees build using a (polymorphic) comparison function, similarly to the maps of the standard library.
Another difference is that the type of values in the map is independent from the type of the keys, allowing keys to be associated with different values in different maps. i.e. we map 'a key to any ('a, 'b) value type, whereas dmap only maps 'a key to 'a or 'a value.
dmap also works with OCaml >= 4.12, whereas we require OCaml >= 4.14.
Contributions and bug reports
Any contributions are welcome!
You can report any bug, issues, or desired features using the Github issue tracker. Please include OCaml, dune, and library version information in you bug reports.
If you want to contribute code, feel free to fork the repository on Github and open a pull request. By doing so you agree to release your code under this project's license (LGPL-2.1).
There is no imposed coding style for this repository, here are just a few guidelines and conventions:
Module type names should use SCREAMING_SNAKE_CASE.
Module and functor names use PascalCase, functors names start with Make.
Even though the library implements homogeneous maps as a specialization of heterogeneous ones, the naming convention is that no prefix means homogeneous, and all heterogeneous objects are prefixed with heterogeneous.
Please consider adding test for new features/fixed bugs if at all possible. This library uses a QuickCheck framework for tests.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..cf3033d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HashconsedNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..5cc192d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HashconsedNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values for a hash-consed maps.
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/index.html.json
new file mode 100644
index 0000000..36e0d38
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HashconsedNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Gives a unique number to each node like NodeWithId, but also performs hash-consing. So two maps with the same bindings will always be physically equal. See Hash-consed maps and sets for more details on this.
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
Using a single HashconsedNode in multiple MakeCustomMap functors will result in all those maps being hash-consed together (stored in the same hash-table, same numbering system).
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.
Returns a unique number for each map, the hash-consed identifier of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Maps with the same identifier are also physically equal: to_int m1 = to_int m2 implies m1 == m2.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedSetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedSetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..483a415
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedSetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HashconsedSetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedSetNode/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedSetNode/index.html.json
new file mode 100644
index 0000000..b13985e
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashconsedSetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HashconsedSetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
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.
Returns a unique number for each map, the hash-consed identifier of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Maps with the same identifier are also physically equal: to_int m1 = to_int m2 implies m1 == m2.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashedValue/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashedValue/index.html.json
new file mode 100644
index 0000000..0d4404a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HashedValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HashedValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Generic implementation of HASHED_VALUE. Uses Hashtbl.hash for hashing and physical equality for equality. Note that this may lead to maps of different types having the same identifier (MakeHashconsedMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.
","content":"
type'a t = 'a
The type of values for a hash-consed maps.
Unlike VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : t1 t and b : t2 t yield polyeq a b = true, then let a' : t2 t = Obj.magic a and let b' : t1 t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type 'a t which doesn't depend on 'a, in which case casting form 'a t to 'b t is always safe:
type _ t = foo\u000Alet cast : type a b. a t -> b t = fun x -> x\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type _ t =\u000A | T_Int : int -> int t\u000A | T_Bool : bool -> bool t\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HashedValue. Note however that using this function can lead to identifiers no longer being unique across types. They will still be unique and behave as expected within a certain type, but since some values of different types can physically equal, we may have identifer clashes:
# 97 == Obj.magic 'a';;\u000A- : bool = true
module HMap = MakeHashconsedMap(struct\u000A type t = int\u000A let to_int x = x\u000Aend)(HashedValue)()
This issue does not happen with the two previous variants, since they both only return true on the same types.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HeterogeneousHashedValue/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HeterogeneousHashedValue/index.html.json
new file mode 100644
index 0000000..eadfd85
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HeterogeneousHashedValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HeterogeneousHashedValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/HomogeneousValue/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HomogeneousValue/index.html.json
new file mode 100644
index 0000000..c140390
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/HomogeneousValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HomogeneousValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Default implementation of HETEROGENEOUS_VALUE, to use when the type of the value in a heterogeneous map does not depend on the type of the key, only on the type of the map.
","content":"
type('a, 'map) t = 'map
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..05d72de
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/index.html.json
new file mode 100644
index 0000000..c130173
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..4161087
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..66c4792
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-3-Node/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-3-Node/index.html.json
new file mode 100644
index 0000000..eef5e35
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/argument-3-Node/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Node","href":"#","kind":"argument-3"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/index.html.json
new file mode 100644
index 0000000..9838ac2
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
The type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..ab789c3
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..83c7123
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/index.html.json
new file mode 100644
index 0000000..37610a6
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
","content":"
includeBASE_MAP\u000A withtype'a key = 'aelt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNODE.t
includeNODE\u000A withtype'a key = 'aelt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNODE.t
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..eba4b68
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/argument-2-NODE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/argument-2-NODE/index.html.json
new file mode 100644
index 0000000..d011bdc
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/argument-2-NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"NODE","href":"#","kind":"argument-2"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/index.html.json
new file mode 100644
index 0000000..691d69f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomHeterogeneousSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomHeterogeneousSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..daa22f4
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..5cd68c3
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/index.html.json
new file mode 100644
index 0000000..74c8c9a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..6e4b7ea
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/WithForeign/index.html.json
new file mode 100644
index 0000000..d19b7f1
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..81c2f86
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..1212b48
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'a t
The type of values. A 'map map maps key to 'map value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-3-Node/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-3-Node/index.html.json
new file mode 100644
index 0000000..1f85d30
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/argument-3-Node/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomMap","href":"../index.html","kind":"module"},{"name":"Node","href":"#","kind":"argument-3"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/index.html.json
new file mode 100644
index 0000000..ced581e
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
Create a homogeneous map with a custom NODE. Also allows customizing the map values
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..cf20864
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..b997d8b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/index.html.json
new file mode 100644
index 0000000..d0749c5
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
","content":"
includeBASE_MAP\u000A withtype_ key = elt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNode.t
includeNODE\u000A withtype_ key = elt\u000A withtype(_, _) value = unit\u000A withtype'a t = 'aNode.t
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..5db67e2
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/argument-2-Node/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/argument-2-Node/index.html.json
new file mode 100644
index 0000000..a2fde40
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/argument-2-Node/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomSet","href":"../index.html","kind":"module"},{"name":"Node","href":"#","kind":"argument-2"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/index.html.json
new file mode 100644
index 0000000..42f0923
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeCustomSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..72c4f79
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/index.html.json
new file mode 100644
index 0000000..90a863a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..c98aec5
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..c8b2401
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values for a hash-consed maps.
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/index.html.json
new file mode 100644
index 0000000..0686b9b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..ac12319
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..26e53ac
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/index.html.json
new file mode 100644
index 0000000..134af47
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..4d75f46
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/index.html.json
new file mode 100644
index 0000000..9217619
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedHeterogeneousSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedHeterogeneousSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..68ed332
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..26e7fce
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/index.html.json
new file mode 100644
index 0000000..1ad5be0
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..2f34243
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/WithForeign/index.html.json
new file mode 100644
index 0000000..508c78f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..a66777e
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..2fea073
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'a t
The type of values for a hash-consed maps.
Unlike VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : t1 t and b : t2 t yield polyeq a b = true, then let a' : t2 t = Obj.magic a and let b' : t1 t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type 'a t which doesn't depend on 'a, in which case casting form 'a t to 'b t is always safe:
type _ t = foo\u000Alet cast : type a b. a t -> b t = fun x -> x\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type _ t =\u000A | T_Int : int -> int t\u000A | T_Bool : bool -> bool t\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HashedValue. Note however that using this function can lead to identifiers no longer being unique across types. They will still be unique and behave as expected within a certain type, but since some values of different types can physically equal, we may have identifer clashes:
# 97 == Obj.magic 'a';;\u000A- : bool = true
module HMap = MakeHashconsedMap(struct\u000A type t = int\u000A let to_int x = x\u000Aend)(HashedValue)()
This issue does not happen with the two previous variants, since they both only return true on the same types.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/index.html.json
new file mode 100644
index 0000000..2d727f2
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Hash-consed version of MAP. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed maps.
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..cbbd622
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..390e589
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/index.html.json
new file mode 100644
index 0000000..91cb93f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..9abe574
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/index.html.json
new file mode 100644
index 0000000..963a5c8
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHashconsedSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHashconsedSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Hash-consed version of SET. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed sets.
This is a generative functor, as calling it creates a new hash-table to store the created nodes, and a reference to store the next unallocated identifier. Maps/sets from different hash-consing functors (even if these functors have the same arguments) will have different (incompatible) numbering systems and be stored in different hash-tables (thus they will never be physically equal).
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
Returns the hash-consed id of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..dea897b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json
new file mode 100644
index 0000000..b4afd2b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..c9ce4bc
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..256fe90
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/index.html.json
new file mode 100644
index 0000000..3502e25
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..746ee9a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..a508c32
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json
new file mode 100644
index 0000000..4863ef0
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..ab4a19b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/index.html.json
new file mode 100644
index 0000000..affd439
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeHeterogeneousSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..6691db6
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..473abf9
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/index.html.json
new file mode 100644
index 0000000..c652939
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..fe68775
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/WithForeign/index.html.json
new file mode 100644
index 0000000..78dd5d9
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..785b52f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/index.html.json
new file mode 100644
index 0000000..f54336a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"","content":"
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..1d48c09
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..c56e455
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/index.html.json
new file mode 100644
index 0000000..7e9bfef
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..d5af357
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/index.html.json
new file mode 100644
index 0000000..820b10a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/MakeSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"","content":"
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/argument-1-Key/index.html.json
new file mode 100644
index 0000000..c11770f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"NodeWithId","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/argument-2-Value/index.html.json
new file mode 100644
index 0000000..3bfcde5
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"NodeWithId","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/index.html.json
new file mode 100644
index 0000000..2dc298d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/NodeWithId/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NodeWithId","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hash-tables.
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.
This is not hash-consing. Equal nodes created separately will have different identifiers. On the flip side, nodes with equal identifiers will always be physically equal.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/SetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..ebc947e
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/SetNode/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SetNode/index.html.json
new file mode 100644
index 0000000..01353d4
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
An optimized representation for sets, i.e. maps to unit: we do not store a reference to unit (note that you can further optimize when you know the representation of the key). This is the node used in MakeHeterogeneousSet and MakeSet.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..b3e4977
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SimpleNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..992e324
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SimpleNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/index.html.json
new file mode 100644
index 0000000..e6ac250
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/SimpleNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SimpleNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/Value/index.html.json
new file mode 100644
index 0000000..f99755c
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
The type of values. A 'map map maps key to 'map value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..2ce648d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..b20af62
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/index.html.json
new file mode 100644
index 0000000..1a7fbc5
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WeakNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
NODE used to implement weak key hashes (the key-binding pair is an Ephemeron, the reference to the key is weak, and if the key is garbage collected, the binding disappears from the map
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..9a3e167
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakSetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakSetNode/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakSetNode/index.html.json
new file mode 100644
index 0000000..27e44bd
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WeakSetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WeakSetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
Both a WeakNode and a SetNode, useful to implement Weak sets.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/WrappedHomogeneousValue/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WrappedHomogeneousValue/index.html.json
new file mode 100644
index 0000000..39b5d0b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/WrappedHomogeneousValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WrappedHomogeneousValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Same as HomogeneousValue, but uses a wrapper (unboxed) type instead of direct equality. This avoids a problem in the typechecker with overly eager simplification of aliases. More info on the OCaml discourse post.
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/index.html.json
new file mode 100644
index 0000000..f7036c8
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../index.html","kind":"page"},{"name":"PatriciaTree","href":"#","kind":"module"}],"toc":[{"title":"Nodes","href":"#nodes","children":[]},{"title":"Map signatures","href":"#map-signatures","children":[{"title":"Base map","href":"#base-map","children":[]},{"title":"Heterogeneous maps and sets","href":"#heterogeneous-maps-and-sets","children":[]},{"title":"Homogeneous maps and sets","href":"#homogeneous-maps-and-sets","children":[]}]},{"title":"Keys","href":"#keys","children":[]},{"title":"Values","href":"#values","children":[]},{"title":"Functors","href":"#functors","children":[{"title":"Homogeneous maps and sets","href":"#homogeneous-maps-and-sets_2","children":[]},{"title":"Heterogeneous maps and sets","href":"#heterogeneous-maps-and-sets_2","children":[]},{"title":"Maps and sets with custom nodes","href":"#maps-and-sets-with-custom-nodes","children":[]},{"title":"Hash-consed maps and sets","href":"#hash_consed","children":[]}]},{"title":"Some implementations of NODE","href":"#node_impl","children":[{"title":"Basic nodes","href":"#basic-nodes","children":[]},{"title":"Weak nodes","href":"#weak-nodes","children":[]},{"title":"Hashconsed nodes","href":"#hashconsed-nodes","children":[]}]}],"source_anchor":null,"preamble":"
Association maps from key to values, and sets, implemented with Patricia Trees, allowing fast merge operations by making use of physical equality between subtrees; and custom implementation of tree nodes (allowing normal maps, hash-consed maps, weak key or value maps, sets, custom maps, etc.)
This is similar to OCaml's Map, except that:
The required signature for keys is different, in that we require each key to be mapped to a unique integer identifier.
The implementation uses Patricia Tree, as described in Okasaki and Gill's 1998 paper Fast mergeable integer maps, i.e. it is a space-efficient prefix trie over the big-endian representation of the key's integer identifier.
Example of a 5-bit patricia tree containing five numbers: 0 0b0000, 1 0b0001, 5 0b0101 and 7 0b0111 and -8 0b1111:
The main benefit of Patricia Tree is that their representation is stable (contrary to maps, inserting nodes in any order will return the same shape), which allows different versions of a map to share more subtrees in memory, and the operations over two maps to benefit from this sharing. The functions in this library attempt to maximally preserve sharing and benefit from sharing, allowing very important improvements in complexity and running time when combining maps or sets is a frequent operation.
Finally, the implementation is more customizable, allowing notably (key,value) pairs or different types to be in the same map, or to choose the memory representation of the nodes of the tree.
Some operations like pop_unsigned_minimum and pop_unsigned_maximum make our Set suitable as priority queue (but remember that each element in the queue must map to a distinct integer, and that using the unsigned order means elements with negative priority are seen as greater than elements with positive ones).
","content":"
Note on complexity: in the following, n represents the size of the map when there is one (and |map1| is the number of elements in map1). The term log(n) correspond to the maximum height of the tree, which is log(n) if we assume an even distribution of numbers in the map (e.g. random distribution, or integers chosen contiguously using a counter). The worst-case height is O(min(n,64)) which is actually constant, but not really informative; log(n) corresponds to the real complexity in usual distributions.
val unsigned_lt : int ->int -> bool
All integers comparisons in this library are done according to their unsigned representation. This is the same as signed comparison for same sign integers, but all negative integers are greater than the positives. This means -1 is the greatest possible number, and 0 is the smallest.
Hash-consed nodes also associate a unique number to each node, Unlike NODE_WITH_ID, they also check before instanciating the node whether a similar node already exists. This results in slightly slower constructors (they perform an extra hash-table lookup), but allows for constant time equality and comparison.
Base map signature: a generic 'b map storing bindings of 'a key to ('a,'b) values. All maps and set are a variation of this type, sometimes with a simplified interface.
Heterogeneous maps and sets
Maps and sets with generic keys 'a key and values ('a,'b) value
Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.
type(_, 'b) snd =
| Sndof'b
The typechecker struggles with forall quantification on values if they don't depend on the first parameter, this wrapping allows our code to pass typechecking by forbidding overly eager simplification. Since the type is unboxed, it doesn't introduce any performance overhead.
The signature for maps with a single type for keys and values, a 'a map binds key to 'a value. This is slightly more generic than MAP, which just binds to 'a. It is used for maps that need to restrict their value type, namely Hash-consed maps and sets.
To have heterogeneous keys, we must define a polymorphic equality function. Like in the homogeneous case, it should have the requirement that (to_int a) = (to_int b) ==> polyeq a b = Eq.
Module type used for specifying custom homogeneous value types in MakeCustomMap. For most purposes, use the provided Value implementation. It sets 'a t = 'a, which is the desired effect (maps can map to any value). This is the case in MakeMap. However, for maps like Hash-consed maps and sets, it can be useful to restrict the type of values in order to implement hash and polyeq functions on values. See the HASHED_VALUE module type for more details.
The module type of values, which can be heterogeneous. This can be used to specify how the type of the value depends on that of the key. If the value doesn't depend on the key type, you can use the provided default implementations HomogeneousValue and WrappedHomogeneousValue.
Default implementation of HETEROGENEOUS_VALUE, to use when the type of the value in a heterogeneous map does not depend on the type of the key, only on the type of the map.
Same as HomogeneousValue, but uses a wrapper (unboxed) type instead of direct equality. This avoids a problem in the typechecker with overly eager simplification of aliases. More info on the OCaml discourse post.
Generic implementation of HASHED_VALUE. Uses Hashtbl.hash for hashing and physical equality for equality. Note that this may lead to maps of different types having the same identifier (MakeHashconsedMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.
Heterogeneous maps are 'map map, which store bindings of 'key key to ('key, 'map) value, where 'key key is a GADT, as we must be able to compare keys of different types together.
Similarly, heterogeneous sets store sets of 'key key.
This 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.
Maps and sets with custom nodes
We can also customize the representation and creation of nodes, to gain space or time.
Possibitities include having weak key and/or values, hash-consing, giving unique number to nodes or keeping them in sync with the disk, lazy evaluation and/or caching, adding size information for constant time cardinal functions, etc.
Hash-consed maps and sets uniquely number each of their nodes. Upon creation, they check whether a similar node has been created before, if so they return it, else they return a new node with a new number. With this unique numbering:
equal and compare become constant time operations;
two maps with the same bindings (where keys are compared by KEY.to_int and values by HASHED_VALUE.polyeq) will always be physically equal;
constructors are slightly slower, as they now require a hash-table lookup;
memory usage is increased: nodes store their tags inside themselves, and a global hash-table of all built nodes must be maintained;
hash-consed maps assume their values are immutable;
WARNING: when using physical equality as HASHED_VALUE.polyeq, some maps of different types may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details. Note that this is the case in the default implementations HashedValue and HeterogeneousHashedValue.
All hash-consing functors are generative, since each functor call will create a new hash-table to store the created nodes. Calling a functor twice with same arguments will lead to two numbering systems for identifiers, and thus the types should not be considered compatible.
Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hash-tables.
moduleSetNode\u000A (Key : sig ... end) : \u000A NODEwithtype'a key = 'aKey.tandtype('key, 'map) value = unit
An optimized representation for sets, i.e. maps to unit: we do not store a reference to unit (note that you can further optimize when you know the representation of the key). This is the node used in MakeHeterogeneousSet and MakeSet.
NODE used to implement weak key hashes (the key-binding pair is an Ephemeron, the reference to the key is weak, and if the key is garbage collected, the binding disappears from the map
Gives a unique number to each node like NodeWithId, but also performs hash-consing. So two maps with the same bindings will always be physically equal. See Hash-consed maps and sets for more details on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-BASE_MAP/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-BASE_MAP/index.html.json
new file mode 100644
index 0000000..6b1c424
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-BASE_MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"BASE_MAP","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
Base map signature: a generic 'b map storing bindings of 'a key to ('a,'b) values. All maps and set are a variation of this type, sometimes with a simplified interface.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HASHED_VALUE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HASHED_VALUE/index.html.json
new file mode 100644
index 0000000..0e4fe72
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HASHED_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HASHED_VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
This is the parameter type for homogeneous maps, used in MakeHashconsedMap. A default implementation is provided in HashedValue, using Hashtbl.hash as hash function and physical equality as polyeq.
since 0.10.0
","content":"
type'a t
The type of values for a hash-consed maps.
Unlike VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : t1 t and b : t2 t yield polyeq a b = true, then let a' : t2 t = Obj.magic a and let b' : t1 t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type 'a t which doesn't depend on 'a, in which case casting form 'a t to 'b t is always safe:
type _ t = foo\u000Alet cast : type a b. a t -> b t = fun x -> x\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type _ t =\u000A | T_Int : int -> int t\u000A | T_Bool : bool -> bool t\u000Alet polyeq : type a b. a t -> b t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HashedValue. Note however that using this function can lead to identifiers no longer being unique across types. They will still be unique and behave as expected within a certain type, but since some values of different types can physically equal, we may have identifer clashes:
# 97 == Obj.magic 'a';;\u000A- : bool = true
module HMap = MakeHashconsedMap(struct\u000A type t = int\u000A let to_int x = x\u000Aend)(HashedValue)()
This issue does not happen with the two previous variants, since they both only return true on the same types.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HASH_CONSED_NODE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HASH_CONSED_NODE/index.html.json
new file mode 100644
index 0000000..7f56e40
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HASH_CONSED_NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HASH_CONSED_NODE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Hash-consed nodes also associate a unique number to each node, Unlike NODE_WITH_ID, they also check before instanciating the node whether a similar node already exists. This results in slightly slower constructors (they perform an extra hash-table lookup), but allows for constant time equality and comparison.
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.
Returns a unique number for each map, the hash-consed identifier of the map. Unlike NODE_WITH_ID.to_int, hash-consing ensures that maps which contain the same keys (compared by KEY.to_int) and values (compared by HASHED_VALUE.polyeq) will always be physically equal and have the same identifier.
Maps with the same identifier are also physically equal: to_int m1 = to_int m2 implies m1 == m2.
Note that when using physical equality as HASHED_VALUE.polyeq, some maps of different types a t and b t may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details.
Constant time equality using the hash-consed nodes identifiers. This is equivalent to physical equality. Two nodes are equal if their trees contain the same bindings, where keys are compared by KEY.to_int and values are compared by HASHED_VALUE.polyeq.
Constant time comparison using the hash-consed node identifiers. This order is fully arbitrary, but it is total and can be used to sort nodes. It is based on node ids which depend on the order in which the nodes where created (older nodes having smaller ids).
One useful property of this order is that child nodes will always have a smaller identifier than their parents.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_HASHED_VALUE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_HASHED_VALUE/index.html.json
new file mode 100644
index 0000000..b84f0f3
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_HASHED_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_HASHED_VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Unlike HETEROGENEOUS_VALUE.t, hash-consed values should be immutable. Or, if they do mutate, they must not change their hash value, and still be equal to the same values via polyeq
hash v should return an integer hash for the value v. It is used for hash-consing.
Hashing should be fast, avoid mapping too many values to the same integer and compatible with polyeq (equal values must have the same hash: polyeq v1 v2 = true ==> hash v1 = hash v2).
val polyeq : ('key, 'map_a)t->('key, 'map_b)t-> bool
Polymorphic equality on values.
WARNING: if polyeq a b is true, then casting b to the type of a (and a to the type of b) must be type-safe. Eg. if a : (k, t1) t and b : (k, t2) t yield polyeq a b = true, then let a' : (k,t2) t = Obj.magic a and let b' : (k,t1) t = Obj.magic b must be safe.
Examples of safe implementations include:
Having a type ('key, 'map) t which doesn't depend on 'map (i can depend on 'key), in which case casting form ('key, 'a) t to ('key, 'b) t is always safe:
type ('k, _) t = 'k list\u000Alet cast : type a b. ('k, a) t -> ('k, b) t = fun x -> x\u000Alet polyeq : type a b. ('k, a) t -> ('k, b) t -> bool = fun x y -> x = y
Using a GADT type and examining its constructors to only return true when the constructors are equal:
type (_, _) t =\u000A | T_Int : int -> (unit, int) t\u000A | T_Bool : bool -> (unit, bool) t\u000Alet polyeq : type k a b. (k, a) t -> (k, b) t -> bool = fun x y ->\u000A match x, y with\u000A | T_Int i, T_Int j -> i = j (* Here type a = b = int, we can return true *)\u000A | T_Bool i, T_Bool j -> i && j (* same here, but with a = b = bool *)\u000A | _ -> false (* never return true on heterogeneous cases. *)
Using physical equality:
let polyeq a b = a == Obj.magic b
While this contains an Obj.magic, it is still type safe (OCaml just compares the immediate values) and we can safely cast values from one type to the other if they satisfy this (since they are already physically equal).
This is the implementation used in HeterogeneousHashedValue. Note however that using this function can lead to identifiers no longer being unique across types. See HASHED_VALUE.polyeq for more information on this.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json
new file mode 100644
index 0000000..a70cd50
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_KEY","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The signature of heterogeneous keys.
","content":"
type'key t
The type of generic/heterogeneous keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq, and be fast.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..e6baa70
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json
new file mode 100644
index 0000000..c924d79
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json
new file mode 100644
index 0000000..2cadb60
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..099d864
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..8490d5f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json
new file mode 100644
index 0000000..9b56a13
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json
new file mode 100644
index 0000000..8ec39ef
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on elements.
fold f set acc returns f.f elt_n (... (f.f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_VALUE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_VALUE/index.html.json
new file mode 100644
index 0000000..adf3cbf
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-HETEROGENEOUS_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The module type of values, which can be heterogeneous. This can be used to specify how the type of the value depends on that of the key. If the value doesn't depend on the key type, you can use the provided default implementations HomogeneousValue and WrappedHomogeneousValue.
","content":"
type('key, 'map) t
The type of values. A 'map map maps 'key key to ('key, 'map) value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-KEY/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-KEY/index.html.json
new file mode 100644
index 0000000..fbe1232
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-KEY/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"KEY","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The signature of homogeneous keys (non-generic, unparameterized keys).
","content":"
type t
The type of keys.
It is recommended to use immutable keys. If keys are mutable, any mutations to keys must preserve to_int. Failing to do so will break the patricia trees' invariants.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, and ideally fast.hash-consing keys is a good way to generate such unique identifiers.
Note that since Patricia Trees use unsigned order, negative keys are seen as bigger than positive keys. Be wary of this when using negative keys combined with functions like unsigned_max_binding and pop_unsigned_maximum.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..020e47b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MAP","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..e26b289
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/index.html.json
new file mode 100644
index 0000000..b641781
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..7be3f02
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/WithForeign/index.html.json
new file mode 100644
index 0000000..5f4a8a5
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/index.html.json
new file mode 100644
index 0000000..4220bd3
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MAP","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
The signature for maps with a single type for keys and values, a 'a map binds key to 'a. Most of this interface should be shared with Stdlib.Map.S.
","content":"
type key
The type of keys.
type'a t
A map from key to values of type 'a value.
type'a value = 'a
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..8aa4b85
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..5bbd11a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/index.html.json
new file mode 100644
index 0000000..017cabd
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..a8d9ac1
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/index.html.json
new file mode 100644
index 0000000..7b880ec
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Combination with other kinds of maps. Map2 must use the same KEY.to_int function.
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->\u000A 'map1value option->\u000A ('a, 'map2)Map2.value->\u000A 'map1value option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/index.html.json
new file mode 100644
index 0000000..66891b2
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-MAP_WITH_VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MAP_WITH_VALUE","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
The signature for maps with a single type for keys and values, a 'a map binds key to 'a value. This is slightly more generic than MAP, which just binds to 'a. It is used for maps that need to restrict their value type, namely Hash-consed maps and sets.
","content":"
type key
The type of keys.
type'a t
A map from key to values of type 'a value.
type'a value
Type for values, this is a divergence from Stdlib's Map, but becomes equivalent to it when using MAP, which is just MAP_WITH_VALUE with type 'a value = 'a. On the other hand, it allows defining maps with fixed values, which is useful for hash-consing.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
val pop_unsigned_maximum : 'at->(key * 'avalue * 'at) option
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. O(log(n)) complexity. Uses the unsigned order on KEY.to_int.
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 : key->('avalue option->'avalue option)->'at->'at
update 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.
val fold_on_nonequal_inter : \u000A (key->'avalue->'avalue->'acc->'acc)->\u000A 'at->\u000A 'at->\u000A 'acc->\u000A 'acc
fold_on_nonequal_inter f m1 m2 acc returns f key_n value1_n value2n (... (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 are performed in the unsigned order of KEY.to_int.
fold_on_nonequal_union f m1 m2 acc returns f key_n value1_n value2n (... (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.
Returns true if the predicate holds on all map bindings. Short-circuiting. f is called in increasing unsigned order of KEY.to_int.
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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
map_no_share f m returns a map where the value bound to each key is replaced by f value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
val filter_map_no_share : (key->'avalue->'bvalue option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing unsigned order of KEY.to_int.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'avalue->'bvalue-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'avalue->'avalue-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int. f is never called on physically equal values.
val idempotent_inter : \u000A (key->'avalue->'avalue->'avalue)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing unsigned order of KEY.to_int!. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'avalue->'bvalue->'cvalue)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing unsigned order of KEY.to_int. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'avalue->'avalue->'avalue option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-NODE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-NODE/index.html.json
new file mode 100644
index 0000000..722b6fd
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NODE","href":"#","kind":"module-type"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
This module explains how a node is stored in memory, with functions to create and view nodes.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
","content":"
Types
type'key key
The type of keys.
type('key, 'map) value
The type of value, which depends on the type of the key and the type of the map.
type'map t
The type of the map, which is parameterized by a type.
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-NODE_WITH_ID/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-NODE_WITH_ID/index.html.json
new file mode 100644
index 0000000..4c29d5d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-NODE_WITH_ID/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NODE_WITH_ID","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Associate a unique number to each node, so they can be used as keys in sets or maps.
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.
This is not hash-consing. Equal nodes created separately will have different identifiers. On the flip side, nodes with equal identifiers will always be physically equal.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..de07e5f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"SET","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..6384bcd
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"SET","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the unsigned order of KEY.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/index.html.json
new file mode 100644
index 0000000..c7588ea
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SET","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
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.
Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.
val pop_unsigned_minimum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
val pop_unsigned_maximum : 'mapt->('mapkey_value_pair * 'mapt) option
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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.
type('acc, 'map) polyfold2 = {
f : 'a. 'akey->('a, 'map)value->('a, 'map)value->'acc->'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map)polyfold2->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
val fold_on_nonequal_union : \u000A ('acc, 'map)polyfold2_union->\u000A 'mapt->\u000A 'mapt->\u000A 'acc->\u000A 'acc
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.
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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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\u000A { f = fun _ v1 v2 -> MyValue.equal v1 v2}\u000A m1 m2;;\u000Aval equal : 'a MyMap.t -> 'a MyMap.t -> bool = <fun>
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds
Assumesf.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.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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.
Assumesf.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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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.
Assumesf.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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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
Operation with maps/set of different types. Map2 must use the same KEY.to_int function.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/index.html.json
new file mode 100644
index 0000000..1ae34ce
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-SET/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SET","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.
pop_unsigned_minimum s is Some (elt, s') where elt = unsigned_min_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
pop_unsigned_maximum s is Some (elt, s') where elt = unsigned_max_elt s and s' = remove elt s if s is non empty. Uses the unsigned order on KEY.to_int.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set. Uses the unsigned order on KEY.to_int.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-VALUE/index.html.json b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-VALUE/index.html.json
new file mode 100644
index 0000000..afd42e1
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/PatriciaTree/module-type-VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Module type used for specifying custom homogeneous value types in MakeCustomMap. For most purposes, use the provided Value implementation. It sets 'a t = 'a, which is the desired effect (maps can map to any value). This is the case in MakeMap. However, for maps like Hash-consed maps and sets, it can be useful to restrict the type of values in order to implement hash and polyeq functions on values. See the HASHED_VALUE module type for more details.
since 0.10.0
","content":"
type'a t
The type of values. A 'map map maps key to 'map value. Can be mutable if desired, unless it is being used in Hash-consed maps and sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__10__0/index.html.json b/_data/api/patricia-tree/v0__10__0/index.html.json
new file mode 100644
index 0000000..a75495b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__10__0/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"#","kind":"page"},{"name":"index","href":"#","kind":"leaf-page"}],"toc":[{"title":"Installation","href":"#installation","children":[]},{"title":"Features","href":"#features","children":[]},{"title":"Quick overview","href":"#quick-overview","children":[{"title":"Functors","href":"#functors","children":[]},{"title":"Interfaces","href":"#interfaces","children":[]}]},{"title":"Examples","href":"#examples","children":[{"title":"Homogeneous map","href":"#homogeneous-map","children":[]},{"title":"Heterogeneous map","href":"#heterogeneous-map","children":[]}]},{"title":"Release status","href":"#release-status","children":[]},{"title":"Known issues","href":"#known-issues","children":[]},{"title":"Comparison to other OCaml libraries","href":"#comparison-to-other-ocaml-libraries","children":[{"title":"ptmap and ptset","href":"#ptmap-and-ptset","children":[]},{"title":"dmap","href":"#dmap","children":[]}]},{"title":"Contributions and bug reports","href":"#contributions-and-bug-reports","children":[]}],"source_anchor":null,"preamble":"
Package patricia-tree
This library contains a single module: PatriciaTree.
This is version 0.10.0 of the library. It is known to work with OCaml versions ranging from 4.14 to 5.2.
This is an OCaml library that implements sets and maps as Patricia Trees, as described in Okasaki and Gill's 1998 paper Fast mergeable integer maps. It is a space-efficient prefix trie over the big-endian representation of the key's integer identifier.
The source code of this library is available on Github under an LGPL-2.1 license.
Similar to OCaml's Map and Set, using the same function names when possible and the same convention for order of arguments. This should allow switching to and from Patricia Tree with minimal effort.
The functor parameters (KEY module) requires an injective to_int : t -> int function instead of a compare function. KEY.to_int should be fast, and injective. This works well with hash-consed types.
The Patricia Tree representation is stable, contrary to maps, inserting nodes in any order will return the same shape. This allows different versions of a map to share more subtrees in memory, and the operations over two maps to benefit from this sharing. The functions in this library attempt to maximally preserve sharing and benefit from sharing, allowing very important improvements in complexity and running time when combining maps or sets is a frequent operation.
To do so, these functions often have extra requirements on their argument (e.g. inter f m1 m2 can be optimized by not inspecting common subtrees when f is idempotent). To avoid accidental errors, they are renamed (e.g. to idempotent_inter for the efficient version and nonidempotent_inter_no_share for the general one)
Since our Patricia Tree use big-endian order on keys, the maps and sets are sorted in increasing unsigned order of keys. This means negative keys are sorted above positive keys, with -1 being the largest possible key, and 0 the smallest. This also avoids a bug in Okasaki's paper discussed in QuickChecking Patricia Trees by Jan Mitgaard.
It also affects functions like unsigned_min_binding and pop_unsigned_minimum. They will return the smallest positive integer of both positive and negative keys are present; and not the smallest negative, as one might expect.
Supports generic maps and sets: a 'm map that maps 'k key to ('k, 'm) value. This is especially useful when using GADTs for the type of keys. This is also sometimes called a dependent map.
Allows easy and fast operations across different types of maps and set which have the same type of keys (e.g. an intersection between a map and a set).
Multiple choices for internal representation (NODE), which allows for efficient storage (no need to store a value for sets), or using weak nodes only (values removed from the tree if no other pointer to it exists). This system can also be extended to store size information in nodes if needed.
Exposes a common interface (PatriciaTree.NODE.view) to allow users to write their own pattern matching on the tree structure without depending on the NODE being used.
Additionally, hashconsed versions of heterogeneous/homogeneous maps/sets are available. These provide constant time equality and comparison, and ensure maps/set with the same constants are always physically equal. It comes at the cost of a constant overhead in memory usage (at worst, as hash-consing may allow memory gains) and constant time overhead when calling constructors.
Quick overview
Functors
This library contains a single module, PatriciaTree. The functors used to build maps and sets are the following:
For homogeneous (non-generic) maps and sets: MakeMap and MakeSet. These are similar to the standard library's maps and sets.
module MakeMap(Key: KEY) : MAP with type key = Key.t\u000Amodule MakeSet(Key: KEY) : SET with type elt = Key.t
module MakeHeterogeneousMap(Key: HETEROGENEOUS_KEY)(Value: HETEROGENEOUS_VALUE) :\u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k,'m) value = ('k,'m) Value.t\u000Amodule MakeHeterogeneousSet(Key: HETEROGENEOUS_KEY) : HETEROGENEOUS_SET\u000A with type 'a elt = 'a Key.t
equal and compare become constant time operations;
two maps with the same bindings (where keys are compared by KEY.to_int and values by HASHED_VALUE.polyeq) will always be physically equal;
functions that benefit from sharing will see improved performance;
constructors are slightly slower, as they now require a hash-table lookup;
memory usage is increased: nodes store their tags inside themselves, and a global hash-table of all built nodes must be maintained;
hash-consed maps assume their values are immutable;
WARNING: when using physical equality as HASHED_VALUE.polyeq, some maps of different types may be given the same identifier. See the end of the documentation of HASHED_VALUE.polyeq for details. Note that this is the case in the default implementations HashedValue and HeterogeneousHashedValue.
All hash-consing functors are generative, since each functor call will create a new hash-table to store the created nodes. Calling a functor twice with same arguments will lead to two numbering systems for identifiers, and thus the types should not be considered compatible.
Interfaces
Here is a brief overview of the various module types of our library:
BASE_MAP: the underlying module type of all our trees (maps end sets). It represents a 'b map binding 'a key to ('a,'b) value, as well as all functions needed to manipulate them.
It can be accessed from any of the more specific maps types, thus providing a unified representation, useful for cross map operations. However, for practical purposes, it is often best to use the more specific interfaces:
MAP for homogeneous maps, this interface is close to Stdlib.Map.S.
HETEROGENEOUS_SET for heterogeneous sets (sets of 'a elt). These are just maps to unit, but with a custom node representation to avoid storing unit in nodes.
SET for homogeneous sets, this interface is close to Stdlib.Set.S.
The parameter of our functor are either KEY or HETEROGENEOUS_KEY. These just consist of a type, a (polymorphic) equality function, and an injective to_int coercion.
The heterogeneous map functor also has a HETEROGENEOUS_VALUE parameter to specify the ('a, 'b) value type.
The internal representations of our tree can be customized to use different internal NODE. Each node come with its own private constructors and destructors, as well as a cast to a uniform NODE.view type used for pattern matching.
HashconsedNode: performs hash-consing (it also stores a unique identifier, but checks when building a new node whether a node with similar content already exists);
module IntKey : PatriciaTree.KEY with type t = int = struct\u000A type t = int\u000A let to_int x = x\u000Aend
Use it to instanciate the map/set functors:
module IMap : PatriciaTree.MAP with type key = int = PatriciaTree.MakeMap(IntKey);;\u000Amodule ISet : PatriciaTree.SET with type elt = int = PatriciaTree.MakeSet(IntKey);;
You can now use it as you would any other map:
# let map =\u000A IMap.empty |>\u000A IMap.add 1 "hello" |>\u000A IMap.add 2 "world" |>\u000A IMap.add 3 "how do you do?";;\u000Aval map : string IMap.t = <abstr>
(We also have of_list and of_seq functions for quick initialization)
The strength of Patricia Tree is the speedup of operations on multiple maps with common subtrees. For example, in the following, the idempotent_inter_filter function will skip recursive calls to physically equal subtrees (kept as-is in the intersection). This allows faster than O(n) intersections.
Physical equality is preserved as much as possible, although some intersections may need to build new nodes and won't be fully physically equal, they will still share some subtrees.
# let str = IMap.find 1 map;;\u000Aval str : string = "hello"\u000A# IMap.add 1 str map == map (* already present *);;\u000A- : bool = true\u000A# IMap.add 1 "hello" map == map\u000A (* new string copy isn't physically equal to the old one *);;\u000A- : bool = false
Note that physical equality isn't preserved when creating new copies of values (the newly created string "hello" isn't physically equal to str). It can also fail when maps have the same bindings but were created differently:
For example, you can only keep the bindings of map whose keys are in a given set:
# let set = ISet.of_list [1; 3];;\u000Aval set : ISet.t = <abstr>\u000A# let restricted_map = CrossOperations.nonidempotent_inter\u000A { f = fun _key value () -> value } map set;;\u000Aval restricted_map : string IMap.t = <abstr>\u000A# IMap.to_list map;;\u000A- : (int * string) list = [(1, "hello"); (2, "world"); (3, "how do you do?")]\u000A# IMap.to_list restricted_map;;\u000A- : (int * string) list = [(1, "hello"); (3, "how do you do?")]
Heterogeneous map
Heterogeneous maps work very similarly to homogeneous ones, but come with extra liberty of having a generic type as a key.
Here is a GADT example to use for our keys: a small typed expression language.
type 'a expr =\u000A | G_Const_Int : int -> int expr\u000A | G_Const_Bool : bool -> bool expr\u000A | G_Addition : int expr * int expr -> int expr\u000A | G_Equal : 'a expr * 'a expr -> bool expr
We can create our HETEROGENEOUS_KEY functor parameter using this type has follows:
module Expr : PatriciaTree.HETEROGENEOUS_KEY with type 'a t = 'a expr = struct\u000A type 'a t = 'a expr\u000A\u000A (** Injective, so long as expressions are small enough\u000A (encodes the constructor discriminant in two lowest bits).\u000A Ideally, use a hash-consed type, to_int needs to be fast *)\u000A let rec to_int : type a. a expr -> int = function\u000A | G_Const_Int i -> 0 + 4*i\u000A | G_Const_Bool b -> 1 + 4*(if b then 1 else 0)\u000A | G_Addition(l,r) -> 2 + 4*(to_int l mod 10000 + 10000*(to_int r))\u000A | G_Equal(l,r) -> 3 + 4*(to_int l mod 10000 + 10000*(to_int r))\u000A\u000A (** Full polymorphic equality *)\u000A let rec polyeq : type a b. a expr -> b expr -> (a, b) PatriciaTree.cmp =\u000A fun l r -> match l, r with\u000A | G_Const_Int l, G_Const_Int r -> if l = r then Eq else Diff\u000A | G_Const_Bool l, G_Const_Bool r -> if l = r then Eq else Diff\u000A | G_Addition(ll, lr), G_Addition(rl, rr) -> (\u000A match polyeq ll rl with\u000A | Eq -> polyeq lr rr\u000A | Diff -> Diff)\u000A | G_Equal(ll, lr), G_Equal(rl, rr) -> (\u000A match polyeq ll rl with\u000A | Eq -> (match polyeq lr rr with Eq -> Eq | Diff -> Diff) (* Match required by typechecker *)\u000A | Diff -> Diff)\u000A | _ -> Diff\u000Aend
We can now instanciate our map functor. Note that in the heterogeneous case, we must also specify the value type (second functor argument) and how it depends on the key type (first parameter) and the map type (second parameter). Here the value only depends on the type of the key, not that of the map
module EMap = PatriciaTree.MakeHeterogeneousMap(Expr)(struct type ('a, _) t = 'a end)
You can now use this as you would any other dependent map:
Physical equality preservation allows fast operations on multiple maps with common ancestors. In the heterogeneous case, these functions are a bit more complex since OCaml requires that first-order polymorphic functions be wrapped in records:
# let map2 = EMap.idempotent_inter_filter\u000A { f = fun _key _l _r -> None } (* polymorphic 1rst order functions are wrapped in records *)\u000A (EMap.add (G_Const_Int 0) 8 map)\u000A (EMap.add (G_Const_Int 0) 9 map)\u000Aval map2 : unit EMap.t = <abstr>
Even though map and map2 have the same elements, they may not always be physically equal:
# map == map2;;\u000A- : bool = false
This is because they were created through different processes. They will still share subtrees. If you want to maintain full physical equality (and thus get cheap equality test between maps), use the provided hash-consed maps and sets.
Release status
This should be close to a stable release. It is already being used as part of a larger project successfully, and this usage as helped us mature the interface. As is, we believe the project is usable, and we don't anticipate any major change before 1.0.0. We didn't commit to a stable release straight away as we would like a bit more time using this library before doing so.
Known issues
There is a bug in the OCaml typechecker which prevents us from directly defining non-generic maps as instances of generic maps. To avoid this, non-generic maps use a separate value type ('a, 'b) snd (instead of just using 'b)
type (_, 'b) snd = Snd of 'b [@@unboxed]
It should not incur any extra performance cost as it is unboxed, but can appear when manipulating non-generic maps.
There are other implementations of Patricia Tree in OCaml, namely ptmap and ptset, both by J.C. Filliatre. These are smaller and closer to OCaml's built-in Map and Set, however:
Our library allows using any type key that comes with an injective to_int function, instead of requiring key = int.
We support generic types for keys/elements.
We support operations between sets and maps of different types.
We use a big-endian representation, allowing easy access to min/max elements of maps and trees.
Our interface and implementation tries to maximize the sharing between different versions of the tree, and to benefit from this memory sharing. Theirs do not.
These libraries work with older version of OCaml (>= 4.05 I believe), whereas ours requires OCaml >= 4.14 (for the new interface of Ephemeron used in WeakNode).
dmap
Additionally, there is a dependent map library: dmap, which gave us the idea of making our PatriciaTree dependent. It allows creating type safe dependent maps similar to our heterogeneous maps. However, its maps aren't Patricia trees. They are binary trees build using a (polymorphic) comparison function, similarly to the maps of the standard library.
Another difference is that the type of values in the map is independent from the type of the keys, allowing keys to be associated with different values in different maps. i.e. we map 'a key to any ('a, 'b) value type, whereas dmap only maps 'a key to 'a or 'a value.
dmap also works with OCaml >= 4.12, whereas we require OCaml >= 4.14.
Contributions and bug reports
Any contributions are welcome!
You can report any bug, issues, or desired features using the Github issue tracker. Please include OCaml, dune, and library version information in you bug reports.
If you want to contribute code, feel free to fork the repository on Github and open a pull request. By doing so you agree to release your code under this project's license (LGPL-2.1).
There is no imposed coding style for this repository, here are just a few guidelines and conventions:
Module type names should use SCREAMING_SNAKE_CASE.
Module and functor names use PascalCase, functors names start with Make.
Even though the library implements homogeneous maps as a specialization of heterogeneous ones, the naming convention is that no prefix means homogeneous, and all heterogeneous objects are prefixed with heterogeneous.
Please consider adding test for new features/fixed bugs if at all possible. This library uses a QuickCheck framework for tests.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/HomogeneousValue/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/HomogeneousValue/index.html.json
new file mode 100644
index 0000000..d20ab2a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/HomogeneousValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HomogeneousValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
To use when the type of the value is the same (but the keys can still be heterogeneous).
","content":"
type('a, 'map) t = 'map
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..4073ab5
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeCustom","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..5b1d318
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustom","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/index.html.json
new file mode 100644
index 0000000..5b3dc24
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustom","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
","content":"
includeBASE_MAP\u000A withtype'a t = 'at\u000A withtype_ key = key\u000A withtype('a, 'b) value = ('a, 'b)snd
includeNODE\u000A withtype'a t = 'at\u000A withtype_ key = key\u000A withtype('a, 'b) value = ('a, 'b)snd
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..f57f6a3
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustom","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/WithForeign/index.html.json
new file mode 100644
index 0000000..3cbde5b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustom","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->'map1 option->('a, 'map2)Map2.value->'map1 option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
type('map1, 'map2) polyupdate_multiple_inter = {
f : 'a. key->'map1->('a, 'map2)Map2.value->'map1 option;
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/argument-1-Key/index.html.json
new file mode 100644
index 0000000..7a94b85
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustom","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/argument-2-NODE/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/argument-2-NODE/index.html.json
new file mode 100644
index 0000000..9769493
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/argument-2-NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustom","href":"../index.html","kind":"module"},{"name":"NODE","href":"#","kind":"argument-2"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/index.html.json
new file mode 100644
index 0000000..4065514
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustom/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustom","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basice functions","href":"#basice-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
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 : key->('a option->'a option)->'at->'at
update 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.
Returns true if the predicate holds on all map bindings. 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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing order of keys.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
val filter_map_no_share : (key->'a->'b option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing order of keys.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'a->'a-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'a->'b-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'a->'a-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : (key->'a->'a->'a)->'at->'at->'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing order of keys. f is never called on physically equal values.
val idempotent_inter : (key->'a->'a->'a)->'at->'at->'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing order of keys. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'a->'b->'c)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing order of keys. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'a->'a->'a option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter f m1\u000A m2 (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..2089fd3
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneous","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/WithForeign/index.html.json
new file mode 100644
index 0000000..79496af
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneous","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-1-Key/index.html.json
new file mode 100644
index 0000000..29ea262
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneous","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-2-Value/index.html.json
new file mode 100644
index 0000000..c016848
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneous","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-3-NODE/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-3-NODE/index.html.json
new file mode 100644
index 0000000..c95b885
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/argument-3-NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeCustomHeterogeneous","href":"../index.html","kind":"module"},{"name":"NODE","href":"#","kind":"argument-3"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/index.html.json
new file mode 100644
index 0000000..ca52c43
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeCustomHeterogeneous/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeCustomHeterogeneous","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
The type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..9fde555
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json
new file mode 100644
index 0000000..8a42635
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..ec58522
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json
new file mode 100644
index 0000000..c0bed5d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/index.html.json
new file mode 100644
index 0000000..ad781ec
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHeterogeneousMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..18627d2
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..9dd9a04
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json
new file mode 100644
index 0000000..1ed0448
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..ce9189a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/index.html.json
new file mode 100644
index 0000000..26c758c
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeHeterogeneousSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeHeterogeneousSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"
A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set.
to_list s returns the elements of s as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..4f57fb9
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..85d4416
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/index.html.json
new file mode 100644
index 0000000..dd5dd2d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
","content":"
includeBASE_MAP\u000A withtype'a t = 'at\u000A withtype_ key = key\u000A withtype('a, 'b) value = ('a, 'b)snd
includeNODE\u000A withtype'a t = 'at\u000A withtype_ key = key\u000A withtype('a, 'b) value = ('a, 'b)snd
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..5fd23ca
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/WithForeign/index.html.json
new file mode 100644
index 0000000..de44bf2
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->'map1 option->('a, 'map2)Map2.value->'map1 option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
type('map1, 'map2) polyupdate_multiple_inter = {
f : 'a. key->'map1->('a, 'map2)Map2.value->'map1 option;
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/argument-1-Key/index.html.json
new file mode 100644
index 0000000..dcec610
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeMap","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/index.html.json
new file mode 100644
index 0000000..b86dbb8
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeMap","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basice functions","href":"#basice-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"","content":"
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 : key->('a option->'a option)->'at->'at
update 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.
Returns true if the predicate holds on all map bindings. 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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing order of keys.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
val filter_map_no_share : (key->'a->'b option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing order of keys.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'a->'a-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'a->'b-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'a->'a-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : (key->'a->'a->'a)->'at->'at->'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing order of keys. f is never called on physically equal values.
val idempotent_inter : (key->'a->'a->'a)->'at->'at->'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing order of keys. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'a->'b->'c)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing order of keys. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'a->'a->'a option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter f m1\u000A m2 (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..ee17f4c
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MakeSet","href":"../../../index.html","kind":"module"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..6b2a0ed
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MakeSet","href":"../../index.html","kind":"module"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/index.html.json
new file mode 100644
index 0000000..95d78a0
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeSet","href":"../index.html","kind":"module"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/argument-1-Key/index.html.json
new file mode 100644
index 0000000..a533dec
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MakeSet","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/index.html.json
new file mode 100644
index 0000000..627874a
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/MakeSet/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MakeSet","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}]}],"source_anchor":null,"preamble":"","content":"
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
to_list s returns the elements of s as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/argument-1-Key/index.html.json
new file mode 100644
index 0000000..c11770f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"NodeWithId","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/argument-2-Value/index.html.json
new file mode 100644
index 0000000..faece14
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"NodeWithId","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/index.html.json
new file mode 100644
index 0000000..5d399b7
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/NodeWithId/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NodeWithId","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hashtables.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/SetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..ebc947e
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/SetNode/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SetNode/index.html.json
new file mode 100644
index 0000000..b46a1ca
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
An optimized representation for sets, i.e. maps to unit: we do not store a reference to unit (note that you can further optimize when you know the representation of the key).
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..b3e4977
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SimpleNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..f4f8920
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SimpleNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/index.html.json
new file mode 100644
index 0000000..e481226
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/SimpleNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SimpleNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
This module is such that 'map t = 'map view.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..2ce648d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/argument-2-Value/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/argument-2-Value/index.html.json
new file mode 100644
index 0000000..b245b20
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/argument-2-Value/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakNode","href":"../index.html","kind":"module"},{"name":"Value","href":"#","kind":"argument-2"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type('key, 'map) t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/index.html.json
new file mode 100644
index 0000000..ddccf2d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WeakNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
NODE used to implement weak key hashes (the key-binding pair is an Ephemeron, the reference to the key is weak, and if the key is garbage collected, the binding disappears from the map
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json
new file mode 100644
index 0000000..9a3e167
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakSetNode/argument-1-Key/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"WeakSetNode","href":"../index.html","kind":"module"},{"name":"Key","href":"#","kind":"argument-1"}],"toc":[],"source_anchor":null,"preamble":"","content":"
type'k t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakSetNode/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakSetNode/index.html.json
new file mode 100644
index 0000000..e063af6
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WeakSetNode/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WeakSetNode","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}]}],"source_anchor":null,"preamble":"
Both a WeakNode and a SetNode, useful to implement Weak sets.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/WrappedHomogeneousValue/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WrappedHomogeneousValue/index.html.json
new file mode 100644
index 0000000..02027a9
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/WrappedHomogeneousValue/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"WrappedHomogeneousValue","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"","content":"
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/index.html.json
new file mode 100644
index 0000000..fc9b207
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../index.html","kind":"page"},{"name":"PatriciaTree","href":"#","kind":"module"}],"toc":[{"title":"Nodes","href":"#nodes","children":[]},{"title":"Map signatures","href":"#map-signatures","children":[{"title":"Base map","href":"#base-map","children":[]},{"title":"Heterogeneous maps and sets","href":"#heterogeneous-maps-and-sets","children":[]},{"title":"Homogeneous maps and sets","href":"#homogeneous-maps-and-sets","children":[]}]},{"title":"Keys","href":"#keys","children":[]},{"title":"Functors","href":"#functors","children":[{"title":"Homogeneous maps and sets","href":"#homogeneous-maps-and-sets_2","children":[]},{"title":"Heterogeneous maps and sets","href":"#heterogeneous-maps-and-sets_2","children":[]},{"title":"Maps with custom representation of Nodes","href":"#maps-with-custom-representation-of-nodes","children":[]}]},{"title":"Some implementations of NODE","href":"#some-implementations-of-node","children":[]}],"source_anchor":null,"preamble":"
Association maps from key to values, and sets, implemented with Patricia Trees, allowing fast merge operations by making use of physical equality between subtrees; and custom implementation of tree nodes (allowing normal maps, hash-consed maps, weak key or value maps, sets, custom maps, etc.)
This is similar to OCaml's Map, except that:
The required signature for keys is different, in that we require each key to be mapped to a unique integer identifier.
The implementation uses Patricia Tree, as described in Oksasaki and Gill's 1998 paper "Fast mergeable integer maps", i.e. it is a space-efficient prefix trie over the big-endian representation of the key's integer identifier.
The main benefit of Patricia Tree is that their representation is stable (contrary to maps, inserting nodes in any order will return the same shape), which allows different versions of a map to share more subtrees in memory, and the operations over two maps to benefit from this sharing. The functions in this library attempt to maximally preserve sharing and benefit from sharing, allowing very important improvements in complexity and running time when combining maps or sets is a frequent operation.
Finally, the implementation is more customizable, allowing notably (key,value) pairs or different types to be in the same map, or to choose the memory representation of the nodes of the tree.
Some operations like pop_minimum and pop_maximum make our Set suitable as priority queue (but remember that each element in the queue must map to a distinct integer).
","content":"
Note on complexity: in the following, n represents the size of the map when there is one (and |map1| is the number of elements in map1). The term log(n) correspond to the maximum height of the tree, which is log(n) if we assume an even distribution of numbers in the map (e.g. random distribution, or integers chosen contiguously using a counter). The worst-case height is O(max(n,64)) which is actually constant, but not really informative; log(n) corresponds to the real complexity in usual distributions.
Base map signature: a generic 'b map storing bindings of 'a key to ('a,'b) values. All maps and set are a variation of this type, sometimes with a simplified interface:
Heterogeneous maps and sets
Maps and sets with generic keys 'a key and values ('a,'b) value
Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.
type(_, 'b) snd =
| Sndof'b
The typechecker struggles with forall quantification on values if they don't depend on the first parameter, this wrapping allows our code to pass typechecking by forbidding overly eager simplification.
To have heterogeneous keys, we must define a polymorphic equality function. Like in the homogeneous case, it should have the requirement that (to_int a) = (to_int b) ==> polyeq a b = Eq.
This 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.
Maps with custom representation of Nodes
We can also customize the representation and creation of nodes, to gain space or time.
Possibitities include having weak key and/or values, hash-consing, giving unique number to nodes or keeping them in sync with the disk, lazy evaluation and/or caching, etc.
Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hashtables.
moduleSetNode\u000A (Key : sig ... end) : \u000A NODEwithtype'a key = 'aKey.tandtype('key, 'map) value = unit
An optimized representation for sets, i.e. maps to unit: we do not store a reference to unit (note that you can further optimize when you know the representation of the key).
NODE used to implement weak key hashes (the key-binding pair is an Ephemeron, the reference to the key is weak, and if the key is garbage collected, the binding disappears from the map
Both a WeakNode and a SetNode, useful to implement Weak sets.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-BASE_MAP/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-BASE_MAP/index.html.json
new file mode 100644
index 0000000..0e4d9c9
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-BASE_MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"BASE_MAP","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
Base map signature: a generic 'b map storing bindings of 'a key to ('a,'b) values. All maps and set are a variation of this type, sometimes with a simplified interface:
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json
new file mode 100644
index 0000000..fb7a0a5
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_KEY/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_KEY","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
Polymorphic equality function used to compare our keys. It should satisfy (to_int a) = (to_int b) ==> polyeq a b = Eq
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..0a61daf
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json
new file mode 100644
index 0000000..789f0fb
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json
new file mode 100644
index 0000000..189249d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_MAP","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..1081b64
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..4f5cf67
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json
new file mode 100644
index 0000000..c87cf37
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json
new file mode 100644
index 0000000..7642021
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-HETEROGENEOUS_SET/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"HETEROGENEOUS_SET","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.
The type of elt is replaced by a type constructor 'k elt. Because of that, most higher-order arguments require higher-ranking polymorphism, and we provide records that allows to pass them as arguments (e.g. polyfold, polypretty, etc.)
The type of some return values, must be concealed existentially, hence the Any constructor.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set.
to_list s returns the elements of s as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-KEY/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-KEY/index.html.json
new file mode 100644
index 0000000..b6a74ca
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-KEY/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"KEY","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The signature of keys when they are all of the same type.
A unique identifier for values of the type. Usually, we use a fresh counter that is increased to give a unique id to each object. Correctness of the operations requires that different values in a tree correspond to different integers.
Must be injective, return only positive values, and ideally fast
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..5638557
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"MAP","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..93f8f5d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/index.html.json
new file mode 100644
index 0000000..36ec684
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
","content":"
includeBASE_MAP\u000A withtype'a t = 'at\u000A withtype_ key = key\u000A withtype('a, 'b) value = ('a, 'b)snd
includeNODE\u000A withtype'a t = 'at\u000A withtype_ key = key\u000A withtype('a, 'b) value = ('a, 'b)snd
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..db3f78f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"MAP","href":"../../index.html","kind":"module-type"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/WithForeign/index.html.json
new file mode 100644
index 0000000..0d2900c
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"MAP","href":"../index.html","kind":"module-type"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
Like nonidempotent_inter, but takes another map as an argument.
type('map1, 'map2) polyupdate_multiple = {
f : 'a. key->'map1 option->('a, 'map2)Map2.value->'map1 option;
}
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update (but more efficient) update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
type('map1, 'map2) polyupdate_multiple_inter = {
f : 'a. key->'map1->('a, 'map2)Map2.value->'map1 option;
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/index.html.json
new file mode 100644
index 0000000..ca2c260
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-MAP/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"MAP","href":"#","kind":"module-type"}],"toc":[{"title":"Basice functions","href":"#basice-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Operations on pairs of maps","href":"#operations-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
The signature for maps with a single type for keys and values. Most of this interface should be shared with Stdlib.Set.S.
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 : key->('a option->'a option)->'at->'at
update 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.
Returns true if the predicate holds on all map bindings. 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 returns a map where the value bound to each key is replaced by f value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
mapi f m returns a map where the value bound to each key is replaced by f key value. The subtrees for which the returned value is physically the same (i.e. f key value == value for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
mapi_no_share f m returns a map where the value bound to each key is replaced by f key value. O(n) complexity. f is called in increasing order of keys.
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). The subtrees for which the returned value is physically the same (i.e. f key value = Some v with value == v for all the keys in the subtree) are guaranteed to be physically equal to the original subtree. O(n) complexity. f is called in increasing order of keys.
val filter_map_no_share : (key->'a->'b option)->'at->'bt
filter_map m f returns a map where the value bound to each key is removed (if f key value returns None), or is replaced by v ((if f key value returns Some v). O(n) complexity. f is called in increasing order of keys.
Operations on pairs of maps
The following functions combine two maps. It is key for the performance, when we have large maps who share common subtrees, not to visit the nodes in these subtrees. Hence, we have specialized versions of these functions that assume properties of the function parameter (reflexive relation, idempotent operation, etc.)
When we cannot enjoy these properties, our functions explicitly say so (with a nonreflexive or nonidempotent prefix). The names are a bit long, but having these names avoids using an ineffective code by default, by forcing to know and choose between the fast and slow version.
It is also important to not visit a subtree when there merging this subtree with Empty; hence we provide union and inter operations.
val reflexive_same_domain_for_all2 : \u000A (key->'a->'a-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. We assume that f is reflexive (i.e. f key value value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val nonreflexive_same_domain_for_all2 : \u000A (key->'a->'b-> bool)->\u000A 'at->\u000A 'bt->\u000A bool
nonreflexive_same_domain_for_all2 f map1 map2 returns true if map1 and map2 have the same keys, and f key value1 value2 returns true for each mapping pair of keys. The complexity is O(min(|map1|,|map2|)).
val reflexive_subset_domain_for_all2 : \u000A (key->'a->'a-> bool)->\u000A 'at->\u000A 'at->\u000A bool
reflexive_subset_domain_for_all2 f map1 map2 returns true if all the keys of map1 also are in map2, and f key (find map1\u000A key) (find map2 key) returns true when both keys are present in the map. We assume that f is reflexive (i.e. f key value\u000A value returns true) to avoid visiting physically equal subtrees of map1 and map2. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.
val idempotent_union : (key->'a->'a->'a)->'at->'at->'at
idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtreess in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing order of keys. f is never called on physically equal values.
val idempotent_inter : (key->'a->'a->'a)->'at->'at->'at
idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. We assume that f is idempotent (i.e. f key value value == value) to avoid visiting physically equal subtrees of map1 and map2, and also to preserve physical equality of the subtrees in that case. The complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2. f is called in increasing order of keys. f is never called on physically equal values.
val nonidempotent_inter_no_share : \u000A (key->'a->'b->'c)->\u000A 'at->\u000A 'bt->\u000A 'ct
nonidempotent_inter_no_share f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f is used to combine the values a key is mapped in both maps. f does not need to be idempotent, which imply that we have to visit physically equal subtrees of map1 and map2. The complexity is O(log(n)*min(|map1|,|map2|)). f is called in increasing order of keys. f is called on every shared binding.
val idempotent_inter_filter : \u000A (key->'a->'a->'a option)->\u000A 'at->\u000A 'at->\u000A 'at
idempotent_inter_filter f m1 m2 is like idempotent_inter f m1\u000A m2 (assuming idempotence, using and preserving physically equal subtrees), but it also removes the key->value bindings for which f returns None.
slow_merge f m1 m2 returns a map whose keys are a subset of the keys of m1 and m2. The f function is used to combine keys, similarly to the Map.merge function. This funcion has to traverse all the bindings in m1 and m2; its complexity is O(|m1|+|m2|). Use one of faster functions above if you can.
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-NODE/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-NODE/index.html.json
new file mode 100644
index 0000000..b2b19bb
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-NODE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NODE","href":"#","kind":"module-type"}],"toc":[{"title":"Types","href":"#types","children":[]},{"title":"Constructors: build values","href":"#constructors:-build-values","children":[]},{"title":"Destructors: access the value","href":"#destructors:-access-the-value","children":[]}],"source_anchor":null,"preamble":"
This module explains how a node is stored in memory, with functions to create and view nodes.
We use a uniform type 'map view to pattern match on maps and sets The actual types 'map t can be a bit different from 'map view to allow for more efficient representations, but view should be a constant time operation for quick conversions.
","content":"
Types
type'key key
The type of keys.
type('key, 'map) value
The type of value, which depends on the type of the key and the type of the map.
type'map t
The type of the map, which is parameterized by a type.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
Convert the map to a view. Should be constant time.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-NODE_WITH_ID/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-NODE_WITH_ID/index.html.json
new file mode 100644
index 0000000..334251f
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-NODE_WITH_ID/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"NODE_WITH_ID","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
new file mode 100644
index 0000000..12343df
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/argument-1-Map2/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../../index.html","kind":"module"},{"name":"SET","href":"../../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../../index.html","kind":"module"},{"name":"WithForeign","href":"../index.html","kind":"module"},{"name":"Map2","href":"#","kind":"argument-1"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of maps","href":"#functions-on-pairs-of-maps","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"","content":"
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
to_list m returns the bindings of m as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json
new file mode 100644
index 0000000..5cce6be
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/WithForeign/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../../index.html","kind":"module"},{"name":"SET","href":"../../index.html","kind":"module-type"},{"name":"BaseMap","href":"../index.html","kind":"module"},{"name":"WithForeign","href":"#","kind":"module"}],"toc":[{"title":"Parameters","href":"#parameters","children":[]},{"title":"Signature","href":"#signature","children":[]}],"source_anchor":null,"preamble":"
val update_multiple_from_foreign : \u000A 'bMap2.t->\u000A ('a, 'b)polyupdate_multiple->\u000A 'at->\u000A 'at
This is equivalent to multiple calls to update, but more efficient. update_multiple_from_foreign m_from f m_to is the same as calling update k {f=fun v_to -> f.f k v_to v_from} m_to on all bindings (k, v_from) of m_from, i.e. update_multiple_from_foreign m_from f m_to calls f.f on every key of m_from, says if the corresponding value also exists in m_to, and adds or remove the element in m_to depending on the value of f.f. f.f is called in the order of Key.to_int. O(size(m_from) + size(m_to)) complexity.
update_multiple_from_inter_with_foreign m_from f m_to is the same as update_multiple_from_foreign, except that instead of updating for all keys in m_from, it only updates for keys that are both in m_from and m_to.
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/index.html.json
new file mode 100644
index 0000000..b05a691
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/BaseMap/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../../index.html","kind":"module"},{"name":"SET","href":"../index.html","kind":"module-type"},{"name":"BaseMap","href":"#","kind":"module"}],"toc":[],"source_anchor":null,"preamble":"
Underlying basemap, for cross map/set operations
This 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 type of 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.)
The type of the map (t) is still parameterized by an argument ('m t)
The type of value depend on both the type of the key and the type of the map, hence the type ('k,'m) value.
The type of some return values, like key-value pairs, must be concealed existentially, hence the KeyValue constructor.
Branching bit contains only one bit set; the corresponding mask is (branching_bit - 1). The prefixes are normalized: the bits below the branching bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
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.
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.
update 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.
val add : 'keykey->('key, 'map)value->'mapt->'mapt
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.
Iterators
val split : 'keykey->'mapt->'mapt * ('key, 'map)value option * 'mapt
split key map splits the map into:
submap of map whose keys are smaller than key
value associated to key (if present)
submap of map whose keys are bigger than key Where the order is given by Key.to_int.
val fold : ('acc, 'map)polyfold->'mapt->'acc->'acc
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 order given by Key.to_int.
for_all f m checks that f holds on all bindings of m7 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).
val filter_map_no_share : ('map1, 'map2)polyfilter_map->'map1t->'map2t
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 order given by Key.to_int.
type'map polypretty = {
f : 'a. Stdlib.Format.formatter ->'akey->('a, 'map)value-> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A 'mappolypretty->\u000A Stdlib.Format.formatter ->\u000A 'mapt->\u000A unit
Pretty-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 order given by Key.to_int
Functions on pairs of maps
type('map1, 'map2) polysame_domain_for_all2 = {
f : 'a. 'akey->('a, 'map1)value->('a, 'map2)value-> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_same_domain_for_all2 f m1 m2 is true if and only if
m1 and m2 have the same domain (set of keys)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
It is useful to implement equality on maps:
let equal m1 m2 = reflexive_same_domain_for_all2\u000A { f = fun _ v1 v2 -> Value.equal v1 v2}\u000A m1 m2
val nonreflexive_same_domain_for_all2 : \u000A ('map1, 'map2)polysame_domain_for_all2->\u000A 'map1t->\u000A 'map2t->\u000A bool
nonreflexive_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 order of Key.to_int. Exits early if the domains mismatch.
val reflexive_subset_domain_for_all2 : \u000A ('map, 'map)polysame_domain_for_all2->\u000A 'mapt->\u000A 'mapt->\u000A bool
reflexive_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)
for all bindings (k, v1) in m1 and (k, v2) in m2, f.f k v1 v2 holds @assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending order of Key.to_int. Exits early if the domains mismatch.
val idempotent_union : ('a, 'a, 'a)polyunion->'at->'at->'at
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 order given by 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.
val idempotent_inter : ('a, 'a, 'a)polyinter->'at->'at->'at
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 order given by 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.
val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c)polyinter->\u000A 'at->\u000A 'bt->\u000A 'ct
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 order of keys. O(n) complexity
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/index.html.json
new file mode 100644
index 0000000..8194c0d
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-SET/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"SET","href":"#","kind":"module-type"}],"toc":[{"title":"Basic functions","href":"#basic-functions","children":[]},{"title":"Iterators","href":"#iterators","children":[]},{"title":"Functions on pairs of sets","href":"#functions-on-pairs-of-sets","children":[]},{"title":"Conversion functions","href":"#conversion-functions","children":[]}],"source_anchor":null,"preamble":"
Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.
split elt set returns s_lt, present, s_gt where s_lt contains all elements of set smaller than elt, s_gt all those greater than elt, and present is true if elt is in set.
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter ->unit -> unit)->\u000A (Stdlib.Format.formatter ->elt-> unit)->\u000A Stdlib.Format.formatter ->\u000A t->\u000A unit
Pretty prints the set, pp_sep is called once between each element, it defaults to Format.pp_print_cut
to_list s returns the elements of s as a list, in increasing order of Key.to_int
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-VALUE/index.html.json b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-VALUE/index.html.json
new file mode 100644
index 0000000..7f9d188
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/PatriciaTree/module-type-VALUE/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"../../index.html","kind":"page"},{"name":"PatriciaTree","href":"../index.html","kind":"module"},{"name":"VALUE","href":"#","kind":"module-type"}],"toc":[],"source_anchor":null,"preamble":"
The moodule type of values, which can be heterogeneous.
","content":"
type('key, 'map) t
"}
\ No newline at end of file
diff --git a/_data/api/patricia-tree/v0__9__0/index.html.json b/_data/api/patricia-tree/v0__9__0/index.html.json
new file mode 100644
index 0000000..1481f8b
--- /dev/null
+++ b/_data/api/patricia-tree/v0__9__0/index.html.json
@@ -0,0 +1 @@
+{"type":"documentation","uses_katex":false,"breadcrumbs":[{"name":"patricia-tree","href":"#","kind":"page"},{"name":"index","href":"#","kind":"leaf-page"}],"toc":[{"title":"Installation","href":"#installation","children":[]},{"title":"Features","href":"#features","children":[]},{"title":"Quick overview","href":"#quick-overview","children":[{"title":"Functors","href":"#functors","children":[]},{"title":"Interfaces","href":"#interfaces","children":[]}]},{"title":"Examples","href":"#examples","children":[{"title":"Homogeneous map","href":"#homogeneous-map","children":[]},{"title":"Heterogeneous map","href":"#heterogeneous-map","children":[]}]},{"title":"Release status","href":"#release-status","children":[]},{"title":"Known issues","href":"#known-issues","children":[]},{"title":"Comparison to other OCaml libraries","href":"#comparison-to-other-ocaml-libraries","children":[{"title":"ptmap and ptset","href":"#ptmap-and-ptset","children":[]},{"title":"dmap","href":"#dmap","children":[]}]},{"title":"Contributions and bug reports","href":"#contributions-and-bug-reports","children":[]}],"source_anchor":null,"preamble":"
Package patricia-tree
This library contains a single module: PatriciaTree.
This is version 0.9.0 of the library. It is known to work with OCaml versions ranging from 4.14 to 5.2.
This is an OCaml library that implements sets and maps as Patricia Trees, as described in Okasaki and Gill's 1998 paper Fast mergeable integer maps. It is a space-efficient prefix trie over the big-endian representation of the key's integer identifier.
The source code of this library is available on Github under an LGPL-2.1 license.
Similar to OCaml's Map and Set, using the same function names when possible and the same convention for order of arguments. This should allow switching to and from Patricia Tree with minimal effort.
The functor parameters (PatriciaTree.KEY module) requires an injective to_int : t -> int function instead of a compare function. PatriciaTree.KEY.to_int should be fast, injective, and only return positive integers. This works well with hash-consed types.
The Patricia Tree representation is stable, contrary to maps, inserting nodes in any order will return the same shape. This allows different versions of a map to share more subtrees in memory, and the operations over two maps to benefit from this sharing. The functions in this library attempt to maximally preserve sharing and benefit from sharing, allowing very important improvements in complexity and running time when combining maps or sets is a frequent operation.
To do so, these functions often have extra requirements on their argument (e.g. inter f m1 m2 can be optimized by not inspecting common subtrees when f is idempotent). To avoid accidental errors, they are renamed (e.g. to idempotent_inter for the efficient version and nonidempotent_inter_no_share for the general one)
Since our Patricia Tree use big-endian order on keys, the maps and sets are sorted in increasing order of keys. We only support positive integer keys. This also avoids a bug in Okasaki's paper discussed in QuickChecking Patricia Trees by Jan Mitgaard.
Supports generic maps and sets: a 'm map that maps 'k key to ('k, 'm) value. This is especially useful when using GADTs for the type of keys. This is also sometimes called a dependent map.
Allows easy and fast operations across different types of maps and set (e.g. an intersection between a map and a set), since all sets and maps, no matter their key type, are really positive integer sets or maps.
Multiple choices for internal representation (PatriciaTree.NODE), which allows for efficient storage (no need to store a value for sets), or using weak nodes only (values removed from the tree if no other pointer to it exists). This system can also be extended to store size information in nodes if needed.
Exposes a common interface (PatriciaTree.NODE.view) to allow users to write their own pattern matching on the tree structure without depending on the PatriciaTree.NODE being used.
Quick overview
Functors
This library contains a single module, PatriciaTree. The functors used to build maps and sets are the following:
module MakeHeterogeneousMap(Key: HETEROGENEOUS_KEY)(Value: VALUE) : HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k,'m) value = ('k,'m) Value.t\u000Amodule MakeHeterogeneousSet(Key: HETEROGENEOUS_KEY) : HETEROGENEOUS_SET\u000A with type 'a elt = 'a Key.t
Interfaces
Here is a brief overview of the various module types of our library:
PatriciaTree.BASE_MAP: the underlying module type of all our trees (maps end sets). It represents a 'b map binding 'a key to ('a,'b) value, as well as all functions needed to manipulate them.
It can be accessed from any of the more specific maps types, thus providing a unified representation, useful for cross map operations. However, for practical purposes, it is often best to use the more specific interfaces:
PatriciaTree.HETEROGENEOUS_SET for heterogeneous sets (sets of 'a elt). These are just maps to unit, but with a custom node representation to avoid storing unit in nodes.
The parameter of our functor are either PatriciaTree.KEY or PatriciaTree.HETEROGENEOUS_KEY. These just consist of a type, a (polymorphic) equality function, and an injective to_int coercion.
The heterogeneous map functor also has a PatriciaTree.VALUE parameter to specify the ('a, 'b) value type.
The internal representations of our tree can be customized to use different internal PatriciaTree.NODE. Each node come with its own private constructors and destructors, as well as a cast to a uniform PatriciaTree.NODE.view type used for pattern matching.
(** Create a key struct *)\u000Amodule Int (*: PatriciaTree.KEY*) = struct\u000A type t = int\u000A let to_int x = x\u000Aend\u000A\u000A(** Call the map and/or set functors *)\u000Amodule IMap = PatriciaTree.MakeMap(Int)\u000Amodule ISet = PatriciaTree.MakeSet(Int)\u000A\u000A(** Use all the usual map operations *)\u000Alet map =\u000A IMap.empty |>\u000A IMap.add 1 "hello" |>\u000A IMap.add 2 "world" |>\u000A IMap.add 3 "how do you do?"\u000A (* Also has an [of_list] and [of_seq] operation for initialization *)\u000A\u000Alet _ = IMap.find 1 map (* "hello" *)\u000Alet _ = IMap.cardinal map (* 3 *)\u000A\u000A(** The strength of Patricia Tree is the speedup of operation on multiple maps\u000A with common subtrees. *)\u000Alet map2 =\u000A IMap.idempotent_inter_filter (fun _key _l _r -> None)\u000A (IMap.add 4 "something" map) (IMap.add 5 "something else" map)\u000Alet _ = map == map2 (* true *)\u000A(* physical equality is preserved as much as possible, although some intersections\u000A may need to build new nodes and won't be fully physically equal, they will\u000A still share subtrees if possible. *)\u000A\u000A(** Many operations preserve physical equality whenever possible *)\u000Alet _ = (IMap.add 1 "hello" map) == map (* true: already present *)\u000A\u000A(** Example of cross map/set operation: only keep the bindings of [map]\u000A whose keys are in a given set *)\u000Alet set = ISet.of_list [1; 3]\u000Amodule CrossOperations = IMap.WithForeign(ISet.BaseMap)\u000Alet restricted_map = CrossOperations.nonidempotent_inter\u000A { f = fun _key value () -> value } map set
Heterogeneous map
(** Very small typed expression language *)\u000Atype 'a expr =\u000A | G_Const_Int : int -> int expr\u000A | G_Const_Bool : bool -> bool expr\u000A | G_Addition : int expr * int expr -> int expr\u000A | G_Equal : 'a expr * 'a expr -> bool expr\u000A\u000Amodule Expr : PatriciaTree.HETEROGENEOUS_KEY with type 'a t = 'a expr = struct\u000A type 'a t = 'a expr\u000A\u000A (** Injective, so long as expression are small enough\u000A (encodes the constructor discriminant in two lowest bits).\u000A Ideally, use a hash-consed type, to_int needs to be fast *)\u000A let rec to_int : type a. a expr -> int = function\u000A | G_Const_Int i -> 0 + 4*i\u000A | G_Const_Bool b -> 1 + 4*(if b then 1 else 0)\u000A | G_Addition(l,r) -> 2 + 4*(to_int l mod 10000 + 10000*(to_int r))\u000A | G_Equal(l,r) -> 3 + 4*(to_int l mod 10000 + 10000*(to_int r))\u000A\u000A (** Full polymorphic equality *)\u000A let rec polyeq : type a b. a expr -> b expr -> (a, b) PatriciaTree.cmp =\u000A fun l r -> match l, r with\u000A | G_Const_Int l, G_Const_Int r -> if l = r then Eq else Diff\u000A | G_Const_Bool l, G_Const_Bool r -> if l = r then Eq else Diff\u000A | G_Addition(ll, lr), G_Addition(rl, rr) -> (\u000A match polyeq ll rl with\u000A | Eq -> polyeq lr rr\u000A | Diff -> Diff)\u000A | G_Equal(ll, lr), G_Equal(rl, rr) -> (\u000A match polyeq ll rl with\u000A | Eq -> (match polyeq lr rr with Eq -> Eq | Diff -> Diff) (* Match required by typechecker *)\u000A | Diff -> Diff)\u000A | _ -> Diff\u000Aend\u000A\u000A(** Map from expression to their values: here the value only depends on the type\u000A of the key, not that of the map *)\u000Amodule EMap = PatriciaTree.MakeHeterogeneousMap(Expr)(struct type ('a, _) t = 'a end)\u000A\u000A(** You can use all the usual map operations *)\u000Alet map : unit EMap.t =\u000A EMap.empty |>\u000A EMap.add (G_Const_Bool false) false |>\u000A EMap.add (G_Const_Int 5) 5 |>\u000A EMap.add (G_Addition (G_Const_Int 3, G_Const_Int 6)) 9 |>\u000A EMap.add (G_Equal (G_Const_Bool false, G_Equal (G_Const_Int 5, G_Const_Int 7))) true\u000A\u000Alet _ = EMap.find (G_Const_Bool false) map (* false *)\u000Alet _ = EMap.cardinal map (* 4 *)\u000A\u000A(** Fast operations on multiple maps with common subtrees. *)\u000Alet map2 =\u000A EMap.idempotent_inter_filter\u000A { f = fun _key _l _r -> None } (* polymorphic 1rst order functions are wrapped in records *)\u000A (EMap.add (G_Const_Int 0) 8 map)\u000A (EMap.add (G_Const_Int 0) 9 map)
Release status
This should be close to a stable release. It is already being used as part of a larger project successfully, and this usage as helped us mature the interface. As is, we believe the project is usable, and we don't anticipate any major change before 1.0.0. We didn't commit to a stable release straight away as we would like a bit more time using this library before doing so.
Known issues
There is a bug in the OCaml typechecker which prevents us from directly defining non-generic maps as instances of generic maps. To avoid this, non-generic maps use a separate value type (instead of just using `'b`)
type (_, 'b) snd = Snd of 'b [@@unboxed]
It should not incur any extra performance cost as it is unboxed, but can appear when manipulating non-generic maps.
There are other implementations of Patricia Tree in OCaml, namely ptmap and ptset, both by J.C. Filliatre. These are smaller and closer to OCaml's built-in Map and Set, however:
Our library allows using any type key that comes with an injective to_int function, instead of requiring key = int.
We support generic types for keys/elements.
We support operation between sets and maps of different types.
We use a big-endian representation, allowing easy access to min/max elements of maps and trees.
Our interface and implementation tries to maximize the sharing between different versions of the tree, and to benefit from this memory sharing. Theirs do not.
These libraries work with older version of OCaml (>= 4.05 I believe), whereas ours requires OCaml >= 4.14 (for the new interface of Ephemeron used in PatriciaTree.WeakNode).
Our keys are limited to positive integers.
dmap
Additionally, there is a dependent map library: dmap. It allows creating type safe dependent maps similar to our heterogeneous maps. However, its maps aren't Patricia trees. They are binary trees build using a (polymorphic) comparison function, similarly to the maps of the standard library. Another difference is that the type of values in the map is independent from the type of the keys, (allowing keys to be associated with different values in different maps).
dmap also works with OCaml >= 4.12, whereas we require OCaml >= 4.14.
Contributions and bug reports
Any contributions are welcome!
You can report any bug, issues, or desired features using the Github issue tracker. Please include OCaml, dune, and library version information in you bug reports.
If you want to contribute code, feel free to fork the repository on Github and open a pull request. By doing so you agree to release your code under this project's license (LGPL-2.1).
There is no imposed coding style for this repository, here are just a few guidelines and conventions:
Module type names should use SCREAMING_SNAKE_CASE.
Module and functor names use PascalCase, functors names start with Make.
Even though the library implements homogeneous maps as a specialization of heterogeneous ones, the naming convention is that no prefix means homogeneous, and all heterogeneous objects are prefixed with heterogeneous.
Please consider adding test for new features/fixed bugs if at all possible. This library uses a QuickCheck framework for tests.
"}
\ No newline at end of file
diff --git a/_data/packages.yml b/_data/packages.yml
new file mode 100644
index 0000000..978600a
--- /dev/null
+++ b/_data/packages.yml
@@ -0,0 +1,31 @@
+patricia-tree:
+ # Pretty name to print in headers
+ name: "Patricia Tree"
+ # Description that appears on API page
+ description: |
+ Standalone library for the patricia-tree data structure used in Codex.
+ # Link to repository
+ repository: https://github.com/codex-semantics-library/patricia-tree
+ repository-icon: "fab fa-github"
+ # Latest version, show a warning documentation pages of other version, with a link to latest
+ # A matching _data/api// folder should exist.
+ latest-version: v0.10.0
+ # Dev version (also issue a warning, but a different one)
+ dev-version: main
+ # Shields (img.shield.io) to decorate the package (rendered in _includes/shields.html)
+ shields:
+ - shield: https://img.shields.io/badge/opam-patricia--tree-blue
+ link: https://opam.ocaml.org/packages/patricia-tree/
+ alt-text: Opam package
+ - shield: https://img.shields.io/github/v/release/codex-semantics-library/patricia-tree
+ link: https://github.com/codex-semantics-library/patricia-tree/releases/
+ alt-text: Latest release
+ - shield: https://img.shields.io/badge/OCaml-4.14_--_5.x-blue?logo=ocaml&logoColor=white
+ link: https://github.com/codex-semantics-library/patricia-tree/blob/main/dune-project
+ alt-text: OCaml versions
+ - shield: https://img.shields.io/github/license/codex-semantics-library/patricia-tree
+ link: https://github.com/codex-semantics-library/patricia-tree/blob/main/LICENSE
+ alt-text: License
+ - shield: https://img.shields.io/github/actions/workflow/status/codex-semantics-library/patricia-tree/ocaml.yml
+ link: https://github.com/codex-semantics-library/patricia-tree/actions/workflows/ocaml.yml
+ alt-text: Build
diff --git a/_includes/components/sidebar.html b/_includes/components/sidebar.html
index a6eb2c2..937d15b 100644
--- a/_includes/components/sidebar.html
+++ b/_includes/components/sidebar.html
@@ -1,4 +1,7 @@
{%- comment -%}
+ Most of this is the taken directly from just-the-docs on github. The only change
+ is adding our odoc table of contents.
+
Include as: {%- include components/sidebar.html -%}
Depends on: page(?), site.
Results in: HTML for the side bar.
@@ -18,7 +21,54 @@
- {% include_cached components/site_nav.html %}
+
{% capture nav_footer_custom %}
{%- include nav_footer_custom.html -%}
diff --git a/_includes/head_custom.html b/_includes/head_custom.html
index 8efbc62..6c1b6be 100644
--- a/_includes/head_custom.html
+++ b/_includes/head_custom.html
@@ -4,3 +4,10 @@
{% comment %} {% endcomment %}
+
+{% for css in layout.css %}
+
+{% endfor %}
+{% for css in page.css %}
+
+{% endfor %}
\ No newline at end of file
diff --git a/_includes/shields.html b/_includes/shields.html
new file mode 100644
index 0000000..65a4593
--- /dev/null
+++ b/_includes/shields.html
@@ -0,0 +1,9 @@
+
+ {% for shield in include.package.shields %}
+ {%- if shield.link -%}
+
+ {%- else -%}
+
+ {%- endif -%}
+ {% endfor %}
+
+ {% if page.version == package.dev-version %}
+ This is documentation for the development version of {{package.name}},
+ the latest released version is
+ {% else %}
+ This is documentation for version {{ page.version }} of {{ page.package }},
+ but the latest version is
+ {% endif %}
+ {{ package.latest-version }}.
+
+ Click here
+ to redirect to the latest version.
+