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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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

val hash : ('key, 'map) t -> int

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:

"} \ 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).

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_HASHED_VALUE

Signature

include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('key, 'map) value = ('key, 'map) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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":"

Both a HashconsedNode and a SetNode.

","content":"

Parameters

module Key : HETEROGENEOUS_KEY

Signature

include NODE with type 'a key = 'a Key.t with type ('key, 'map) value = unit

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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

val hash : 'map t -> int

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 : 'a t -> '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 : 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:

"} \ 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":"

Generic implementation of HETEROGENEOUS_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 (MakeHashconsedHeterogeneousMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.

","content":"
type ('k, 'm) t = 'm

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

val hash : ('key, 'map) t -> int

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:

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create an heterogeneous map with a custom NODE.

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 main changes from MAP are:

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_VALUE
module Node : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

Signature

include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t\u000A with type 'm t = 'm Node.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t\u000A with type 'm t = 'm Node.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

The type of value, which depends on the type of the key and the type of the map.

type 'm t = 'm Node.t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a key = 'a elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a NODE.t
include NODE\u000A with type 'a key = 'a elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a NODE.t

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a NODE.t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create an heterogeneous set with a custom NODE.

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module NODE : NODE with type 'a key = 'a Key.t and type ('key, 'map) value = unit

Signature

The main changes from SET are:

type 'a elt = 'a Key.t

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a elt\u000A and type (_, _) value = unit\u000A with type 'a t = 'a NODE.t

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : t -> int

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.

","content":"

Types

type 'a key = Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map Value.t) snd

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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

","content":"

Parameters

module Key : KEY
module Value : VALUE
module Node : \u000A NODE\u000A with type 'a key = Key.t\u000A and type ('key, 'map) value = ('key, 'map Value.t) snd

Signature

type key = Key.t

The type of keys.

type 'm t = 'm Node.t

A map from key to values of type 'a value.

type 'm value = 'm Value.t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type _ key = elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a Node.t
include NODE\u000A with type _ key = elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a Node.t

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a Node.t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : t -> int

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.

","content":"

Types

type 'a key = Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create a homogeneous set with a custom NODE.

","content":"

Parameters

module Key : KEY
module Node : NODE with type 'a key = Key.t and type ('key, 'map) value = unit

Signature

type elt = Key.t

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type _ key = elt\u000A and type (_, _) value = unit\u000A with type 'a t = 'a Node.t

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, in increasing unsigned order of KEY.to_int

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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

val hash : ('key, 'map) t -> int

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:

"} \ 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":"

Hash-consed version of HETEROGENEOUS_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).

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_HASHED_VALUE

Signature

include HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t
include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types. Map2 must use the same KEY.to_int function.

val to_int : 'a t -> 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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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":"

Hash-consed version of HETEROGENEOUS_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).

","content":"

Parameters

module Key : HETEROGENEOUS_KEY

Signature

include HETEROGENEOUS_SET with type 'a elt = 'a Key.t

The main changes from SET are:

type 'a elt = 'a Key.t

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

  • raises Not_found
val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

  • raises Not_found
val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, in increasing unsigned order of KEY.to_int

val to_int : t -> 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.

val equal : t -> t -> bool

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.

val compare : t -> t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : t -> int

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

val hash : 'map t -> int

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 : 'a t -> '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 : 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:

"} \ 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).

","content":"

Parameters

module Key : KEY
module Value : HASHED_VALUE

Signature

include MAP_WITH_VALUE with type key = Key.t and type 'a value = 'a Value.t
type key = Key.t

The type of keys.

type 'a t

A map from key to values of type 'a value.

type 'a value = 'a Value.t

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.

  • since v0.10.0
module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

  • raises Not_found

    if the map is empty.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

  • raises Not_found

    if the map is empty.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

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

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

val to_int : 'a t -> 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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : t -> int

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).

","content":"

Parameters

module Key : KEY

Signature

include SET with type elt = Key.t
type elt = Key.t

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

  • raises Not_found
val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

  • raises Not_found
val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, in increasing unsigned order of KEY.to_int

val to_int : t -> 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.

val equal : t -> t -> bool

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.

val compare : t -> t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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 main changes from MAP are:

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_VALUE

Signature

include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Parameters

module Key : HETEROGENEOUS_KEY

Signature

The main changes from SET are:

type 'a elt = 'a Key.t

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : t -> int

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":"

Parameters

module Key : KEY

Signature

type key = Key.t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : t -> int

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":"

Parameters

module Key : KEY

Signature

type elt = Key.t

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, in increasing unsigned order of KEY.to_int

"} \ 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.

","content":"

Parameters

module Key : sig ... end
module Value : HETEROGENEOUS_VALUE

Signature

include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('key, 'map) value = ('key, 'map) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

Unique number for each node.

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.

","content":"

Parameters

module Key : sig ... end

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

This module is such that 'map t = 'map view. This is the node used in MakeHeterogeneousMap and MakeMap.

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":"

Parameters

module Key : sig ... end
module Value : HETEROGENEOUS_VALUE

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Default implementation of VALUE, used in MakeMap.

","content":"
type 'a t = 'a

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.

","content":"

Parameters

module Key : sig ... end
module Value : HETEROGENEOUS_VALUE

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"

Parameters

module Key : sig ... end

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"
type ('a, 'map) t = ('a, 'map) snd

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:

","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.

# unsigned_lt 2 (-1);;\u000A- : bool = true\u000A# unsigned_lt max_int min_int;;\u000A- : bool = true\u000A# unsigned_lt 3 2;;\u000A- : bool = false\u000A# unsigned_lt 2 3;;\u000A- : bool = true\u000A# unsigned_lt (-2) (-3);;\u000A- : bool = false\u000A# unsigned_lt (-4) (-3);;\u000A- : bool = true\u000A# unsigned_lt 0 0;;\u000A- : bool = false

Using this unsigned order helps avoid a bug described in QuickChecking Patricia Trees by Jan Mitgaard.

type intkey = private int

Private type used to represent prefix stored in nodes. These are integers with all bits after branching bit (included) set to zero

type mask = private int

Private type: integers with a single bit set.

Nodes

module type NODE = sig ... end

This module explains how a node is stored in memory, with functions to create and view nodes.

module type NODE_WITH_ID = sig ... end

Associate a unique number to each node, so they can be used as keys in sets or maps.

module type HASH_CONSED_NODE = sig ... end

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.

Map signatures

Base map

module type BASE_MAP = sig ... end

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

module type HETEROGENEOUS_MAP = sig ... end

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.

module type HETEROGENEOUS_SET = sig ... end

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

Homogeneous maps and sets

Same as above, but simple interfaces for non-generic keys. These are also close to the standard library's interface for sets and maps.

module type SET = sig ... end

Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.

type (_, 'b) snd =
  1. | Snd of '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.

This is due to a bug in the typechecker, more info on the OCaml discourse post.

module type MAP_WITH_VALUE = sig ... end

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.

module type MAP = MAP_WITH_VALUE with type 'a value = 'a

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.

Keys

Keys are the functor arguments used to build the maps.

module type KEY = sig ... end

The signature of homogeneous keys (non-generic, unparameterized keys).

type (_, _) cmp =
  1. | Eq : ('a, 'a) cmp
  2. | Diff : ('a, 'b) cmp

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 HETEROGENEOUS_KEY = sig ... end

The signature of heterogeneous keys.

Values

module type VALUE = sig ... end

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.

module Value : VALUE with type 'a t = 'a

Default implementation of VALUE, used in MakeMap.

module type HETEROGENEOUS_VALUE = sig ... end

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.

module HomogeneousValue : HETEROGENEOUS_VALUE with type ('a, 'map) t = 'map

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.

module WrappedHomogeneousValue : \u000A HETEROGENEOUS_VALUE with type ('a, 'map) t = ('a, 'map) snd

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.

module type HASHED_VALUE = sig ... end

VALUE parameter for Hash-consed maps and sets, as hash-consing requires hashing and comparing values.

module type HETEROGENEOUS_HASHED_VALUE = sig ... end

In order to build Hash-consed maps and sets, we need to be able to hash and compare values.

module HashedValue : HASHED_VALUE with type 'a t = 'a

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.

module HeterogeneousHashedValue : \u000A HETEROGENEOUS_HASHED_VALUE with type ('k, 'm) t = 'm

Generic implementation of HETEROGENEOUS_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 (MakeHashconsedHeterogeneousMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.

Functors

This section presents the functors which can be used to build patricia tree maps and sets.

Homogeneous maps and sets

These are homogeneous maps and set, their keys/elements are a single non-generic type, just like the standard library's Map and Set modules.

module MakeMap (Key : KEY) : MAP with type key = Key.t
module MakeSet (Key : KEY) : SET with type elt = Key.t

Heterogeneous maps and sets

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.

module MakeHeterogeneousSet\u000A (Key : HETEROGENEOUS_KEY) : \u000A HETEROGENEOUS_SET with type 'a elt = 'a Key.t

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

module MakeHeterogeneousMap\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t

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.

See Some implementations of NODE for the provided implementations of NODE, or create your own.

module MakeCustomMap\u000A (Key : KEY)\u000A (Value : VALUE)\u000A (Node : \u000A NODE\u000A with type 'a key = Key.t\u000A and type ('key, 'map) value = ('key, 'map Value.t) snd) : \u000A MAP_WITH_VALUE\u000A with type key = Key.t\u000A and type 'm value = 'm Value.t\u000A and type 'm t = 'm Node.t

Create a homogeneous map with a custom NODE. Also allows customizing the map values

module MakeCustomSet\u000A (Key : KEY)\u000A (Node : NODE with type 'a key = Key.t and type ('key, 'map) value = unit) : \u000A SET with type elt = Key.t and type 'a BaseMap.t = 'a Node.t

Create a homogeneous set with a custom NODE.

module MakeCustomHeterogeneousMap\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_VALUE)\u000A (Node : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t) : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t\u000A and type 'm t = 'm Node.t

Create an heterogeneous map with a custom NODE.

module MakeCustomHeterogeneousSet\u000A (Key : HETEROGENEOUS_KEY)\u000A (NODE : NODE with type 'a key = 'a Key.t and type ('key, 'map) value = unit) : \u000A HETEROGENEOUS_SET\u000A with type 'a elt = 'a Key.t\u000A and type 'a BaseMap.t = 'a NODE.t

Create an heterogeneous set with a custom NODE.

Hash-consed maps and sets

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:

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.

module MakeHashconsedMap (Key : KEY) (Value : HASHED_VALUE) () : sig ... end

Hash-consed version of MAP. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed maps.

module MakeHashconsedSet (Key : KEY) () : sig ... end

Hash-consed version of SET. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed sets.

module MakeHashconsedHeterogeneousSet\u000A (Key : HETEROGENEOUS_KEY)\u000A () : \u000A sig ... end

Hash-consed version of HETEROGENEOUS_SET. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed sets.

module MakeHashconsedHeterogeneousMap\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_HASHED_VALUE)\u000A () : \u000A sig ... end

Hash-consed version of HETEROGENEOUS_MAP. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed maps.

Some implementations of NODE

We provide a few different implementations of NODE, they can be used with the MakeCustomMap, MakeCustomSet, MakeCustomHeterogeneousMap and MakeCustomHeterogeneousSet functors.

Basic nodes

module SimpleNode\u000A (Key : sig ... end)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

This module is such that 'map t = 'map view. This is the node used in MakeHeterogeneousMap and MakeMap.

module NodeWithId\u000A (Key : sig ... end)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A NODE_WITH_ID\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hash-tables.

module SetNode\u000A (Key : sig ... end) : \u000A NODE with type 'a key = 'a Key.t and type ('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.

Weak nodes

module WeakNode\u000A (Key : sig ... end)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

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

module WeakSetNode\u000A (Key : sig ... end) : \u000A NODE with type 'a key = 'a Key.t and type ('key, 'map) value = unit

Both a WeakNode and a SetNode, useful to implement Weak sets.

Hashconsed nodes

module HashconsedNode\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_HASHED_VALUE)\u000A () : \u000A HASH_CONSED_NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

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.

module HashconsedSetNode\u000A (Key : HETEROGENEOUS_KEY)\u000A () : \u000A HASH_CONSED_NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = unit

Both a HashconsedNode and a SetNode.

"} \ 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.

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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":"

VALUE parameter for Hash-consed maps and sets, as hash-consing requires hashing and comparing values.

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.

","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

val hash : 'map t -> int

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 : 'a t -> '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 : 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:

"} \ 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.

See Hash-consed maps and sets for a details on strengths and limits of hash-consing.

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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":"

In order to build Hash-consed maps and sets, we need to be able to hash and compare values.

This is the heterogeneous version of HASHED_VALUE, used to specify a value for heterogeneous maps (in MakeHashconsedHeterogeneousMap). A default implementation is provided in HeterogeneousHashedValue, using Hashtbl.hash as hash function and physical equality as polyeq.

","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

val hash : ('key, 'map) t -> int

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:

"} \ 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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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_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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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_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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

","content":"

The main changes from SET are:

type 'a elt

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, 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.

val to_int : t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, 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-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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, 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-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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

Unique number for each node.

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

","content":"
type elt

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, 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-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.

","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.

This library was written by Matthieu Lemerre, then further improved by Dorian Lesbre, as part of the Codex semantics library, developed at CEA List.

","content":"

Installation

This library can be installed with opam:

opam install patricia-tree

Alternatively, you can clone the source repository and install with dune:

git clone git@github.com:codex-semantics-library/patricia-tree.git\u000Acd patricia-tree\u000Aopan install . --deps-only\u000Adune build -p patricia-tree\u000Adune install\u000A# To build documentation\u000Aopam install . --deps-only --with-doc\u000Adune build @doc

Features

Quick overview

Functors

This library contains a single module, PatriciaTree. The functors used to build maps and sets are the following:

Interfaces

Here is a brief overview of the various module types of our library:

Examples

Homogeneous map

Here is a small example of a non-generic map:

  1. Start by creating a key module:

    module IntKey : PatriciaTree.KEY with type t = int = struct\u000A  type t = int\u000A  let to_int x = x\u000Aend
  2. 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);;
  3. 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)

    # IMap.find 1 map;;\u000A- : string = "hello"\u000A# IMap.cardinal map;;\u000A- : int = 3
  4. 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.

    # let map2 =\u000A    IMap.idempotent_inter_filter (fun _key _l _r -> None)\u000A      (IMap.add 4 "something" map)\u000A      (IMap.add 5 "something else" map);;\u000Aval map2 : string IMap.t = <abstr>\u000A# map == map2;;\u000A- : bool = true

    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:

    # let map3 = IMap.remove 2 map;;\u000Aval map3 : string IMap.t = <abstr>\u000A# IMap.add 2 (IMap.find 2 map) map3 == map;;\u000A- : bool = false

    If you want to maintain full physical equality (and thus get cheap equality test between maps), use the provided hash-consed maps and sets.

  5. Our library also allows cross map/set operations through the WithForeign functors:

    module CrossOperations = IMap.WithForeign(ISet.BaseMap)

    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.

  1. 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
  2. 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)
  3. You can now use this as you would any other dependent map:

    # let 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\u000Aval map : unit EMap.t = <abstr>\u000A# EMap.find (G_Const_Bool false) map;;\u000A- : bool = false\u000A# EMap.find (G_Const_Int 5) map;;\u000A- : int = 5\u000A# EMap.cardinal map;;\u000A- : int = 4
  4. 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.

For more details about this issue, see the OCaml discourse discussion.

Comparison to other OCaml libraries

ptmap and ptset

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:

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:

"} \ 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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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

val hash : ('key, 'map) t -> int

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:

"} \ 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).

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_HASHED_VALUE

Signature

include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('key, 'map) value = ('key, 'map) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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":"

Both a HashconsedNode and a SetNode.

","content":"

Parameters

module Key : HETEROGENEOUS_KEY

Signature

include NODE with type 'a key = 'a Key.t with type ('key, 'map) value = unit

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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

val hash : 'map t -> int

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 : 'a t -> '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 : 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:

"} \ 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":"

Generic implementation of HETEROGENEOUS_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 (MakeHashconsedHeterogeneousMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.

","content":"
type ('k, 'm) t = 'm

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

val hash : ('key, 'map) t -> int

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:

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create an heterogeneous map with a custom NODE.

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 main changes from MAP are:

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_VALUE
module Node : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

Signature

include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t\u000A with type 'm t = 'm Node.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t\u000A with type 'm t = 'm Node.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

The type of value, which depends on the type of the key and the type of the map.

type 'm t = 'm Node.t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a key = 'a elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a NODE.t
include NODE\u000A with type 'a key = 'a elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a NODE.t

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a NODE.t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create an heterogeneous set with a custom NODE.

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module NODE : NODE with type 'a key = 'a Key.t and type ('key, 'map) value = unit

Signature

The main changes from SET are:

type 'a elt = 'a Key.t

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a elt\u000A and type (_, _) value = unit\u000A with type 'a t = 'a NODE.t

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : t -> int

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.

","content":"

Types

type 'a key = Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map Value.t) snd

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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

","content":"

Parameters

module Key : KEY
module Value : VALUE
module Node : \u000A NODE\u000A with type 'a key = Key.t\u000A and type ('key, 'map) value = ('key, 'map Value.t) snd

Signature

type key = Key.t

The type of keys.

type 'm t = 'm Node.t

A map from key to values of type 'a value.

type 'm value = 'm Value.t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, 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/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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type _ key = elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a Node.t
include NODE\u000A with type _ key = elt\u000A with type (_, _) value = unit\u000A with type 'a t = 'a Node.t

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a Node.t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : t -> int

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.

","content":"

Types

type 'a key = Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create a homogeneous set with a custom NODE.

","content":"

Parameters

module Key : KEY
module Node : NODE with type 'a key = Key.t and type ('key, 'map) value = unit

Signature

type elt = Key.t

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type _ key = elt\u000A and type (_, _) value = unit\u000A with type 'a t = 'a Node.t

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, 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/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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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

val hash : ('key, 'map) t -> int

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:

"} \ 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":"

Hash-consed version of HETEROGENEOUS_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).

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_HASHED_VALUE

Signature

include HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t
include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types. Map2 must use the same KEY.to_int function.

val to_int : 'a t -> 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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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":"

Hash-consed version of HETEROGENEOUS_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).

","content":"

Parameters

module Key : HETEROGENEOUS_KEY

Signature

include HETEROGENEOUS_SET with type 'a elt = 'a Key.t

The main changes from SET are:

type 'a elt = 'a Key.t

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

  • raises Not_found
val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

  • raises Not_found
val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, in increasing unsigned order of KEY.to_int

val to_int : t -> 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.

val equal : t -> t -> bool

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.

val compare : t -> t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : t -> int

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

val hash : 'map t -> int

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 : 'a t -> '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 : 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:

"} \ 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).

","content":"

Parameters

module Key : KEY
module Value : HASHED_VALUE

Signature

include MAP_WITH_VALUE with type key = Key.t and type 'a value = 'a Value.t
type key = Key.t

The type of keys.

type 'a t

A map from key to values of type 'a value.

type 'a value = 'a Value.t

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.

  • since v0.10.0
module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

  • raises Not_found

    if the map is empty.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

  • raises Not_found

    if the map is empty.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

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

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

val to_int : 'a t -> 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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : t -> int

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).

","content":"

Parameters

module Key : KEY

Signature

include SET with type elt = Key.t
type elt = Key.t

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

  • raises Not_found
val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

  • raises Not_found
val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, in increasing unsigned order of KEY.to_int

val to_int : t -> 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.

val equal : t -> t -> bool

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.

val compare : t -> t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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 main changes from MAP are:

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : HETEROGENEOUS_VALUE

Signature

include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Parameters

module Key : HETEROGENEOUS_KEY

Signature

The main changes from SET are:

type 'a elt = 'a Key.t

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

val to_int : t -> int

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":"

Parameters

module Key : KEY

Signature

type key = Key.t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, 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/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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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/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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

val to_int : t -> int

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":"

Parameters

module Key : KEY

Signature

type elt = Key.t

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, 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/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.

","content":"

Parameters

module Key : sig ... end
module Value : HETEROGENEOUS_VALUE

Signature

include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('key, 'map) value = ('key, 'map) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

Unique number for each node.

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.

","content":"

Parameters

module Key : sig ... end

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

This module is such that 'map t = 'map view. This is the node used in MakeHeterogeneousMap and MakeMap.

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":"

Parameters

module Key : sig ... end
module Value : HETEROGENEOUS_VALUE

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Default implementation of VALUE, used in MakeMap.

","content":"
type 'a t = 'a

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.

","content":"

Parameters

module Key : sig ... end
module Value : HETEROGENEOUS_VALUE

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"

Parameters

module Key : sig ... end

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"
type ('a, 'map) t = ('a, 'map) snd

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:

","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.

# unsigned_lt 2 (-1);;\u000A- : bool = true\u000A# unsigned_lt max_int min_int;;\u000A- : bool = true\u000A# unsigned_lt 3 2;;\u000A- : bool = false\u000A# unsigned_lt 2 3;;\u000A- : bool = true\u000A# unsigned_lt (-2) (-3);;\u000A- : bool = false\u000A# unsigned_lt (-4) (-3);;\u000A- : bool = true\u000A# unsigned_lt 0 0;;\u000A- : bool = false

Using this unsigned order helps avoid a bug described in QuickChecking Patricia Trees by Jan Mitgaard.

type intkey = private int

Private type used to represent prefix stored in nodes. These are integers with all bits after branching bit (included) set to zero

type mask = private int

Private type: integers with a single bit set.

Nodes

module type NODE = sig ... end

This module explains how a node is stored in memory, with functions to create and view nodes.

module type NODE_WITH_ID = sig ... end

Associate a unique number to each node, so they can be used as keys in sets or maps.

module type HASH_CONSED_NODE = sig ... end

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.

Map signatures

Base map

module type BASE_MAP = sig ... end

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

module type HETEROGENEOUS_MAP = sig ... end

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.

module type HETEROGENEOUS_SET = sig ... end

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

Homogeneous maps and sets

Same as above, but simple interfaces for non-generic keys. These are also close to the standard library's interface for sets and maps.

module type SET = sig ... end

Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.

type (_, 'b) snd =
  1. | Snd of '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.

This is due to a bug in the typechecker, more info on the OCaml discourse post.

module type MAP_WITH_VALUE = sig ... end

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.

module type MAP = MAP_WITH_VALUE with type 'a value = 'a

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.

Keys

Keys are the functor arguments used to build the maps.

module type KEY = sig ... end

The signature of homogeneous keys (non-generic, unparameterized keys).

type (_, _) cmp =
  1. | Eq : ('a, 'a) cmp
  2. | Diff : ('a, 'b) cmp

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 HETEROGENEOUS_KEY = sig ... end

The signature of heterogeneous keys.

Values

module type VALUE = sig ... end

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.

module Value : VALUE with type 'a t = 'a

Default implementation of VALUE, used in MakeMap.

module type HETEROGENEOUS_VALUE = sig ... end

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.

module HomogeneousValue : HETEROGENEOUS_VALUE with type ('a, 'map) t = 'map

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.

module WrappedHomogeneousValue : \u000A HETEROGENEOUS_VALUE with type ('a, 'map) t = ('a, 'map) snd

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.

module type HASHED_VALUE = sig ... end

VALUE parameter for Hash-consed maps and sets, as hash-consing requires hashing and comparing values.

module type HETEROGENEOUS_HASHED_VALUE = sig ... end

In order to build Hash-consed maps and sets, we need to be able to hash and compare values.

module HashedValue : HASHED_VALUE with type 'a t = 'a

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.

module HeterogeneousHashedValue : \u000A HETEROGENEOUS_HASHED_VALUE with type ('k, 'm) t = 'm

Generic implementation of HETEROGENEOUS_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 (MakeHashconsedHeterogeneousMap.to_int), see the documentation of HASHED_VALUE.polyeq for details on this.

Functors

This section presents the functors which can be used to build patricia tree maps and sets.

Homogeneous maps and sets

These are homogeneous maps and set, their keys/elements are a single non-generic type, just like the standard library's Map and Set modules.

module MakeMap (Key : KEY) : MAP with type key = Key.t
module MakeSet (Key : KEY) : SET with type elt = Key.t

Heterogeneous maps and sets

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.

module MakeHeterogeneousSet\u000A (Key : HETEROGENEOUS_KEY) : \u000A HETEROGENEOUS_SET with type 'a elt = 'a Key.t

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

module MakeHeterogeneousMap\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t

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.

See Some implementations of NODE for the provided implementations of NODE, or create your own.

module MakeCustomMap\u000A (Key : KEY)\u000A (Value : VALUE)\u000A (Node : \u000A NODE\u000A with type 'a key = Key.t\u000A and type ('key, 'map) value = ('key, 'map Value.t) snd) : \u000A MAP_WITH_VALUE\u000A with type key = Key.t\u000A and type 'm value = 'm Value.t\u000A and type 'm t = 'm Node.t

Create a homogeneous map with a custom NODE. Also allows customizing the map values

module MakeCustomSet\u000A (Key : KEY)\u000A (Node : NODE with type 'a key = Key.t and type ('key, 'map) value = unit) : \u000A SET with type elt = Key.t and type 'a BaseMap.t = 'a Node.t

Create a homogeneous set with a custom NODE.

module MakeCustomHeterogeneousMap\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_VALUE)\u000A (Node : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t) : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t\u000A and type 'm t = 'm Node.t

Create an heterogeneous map with a custom NODE.

module MakeCustomHeterogeneousSet\u000A (Key : HETEROGENEOUS_KEY)\u000A (NODE : NODE with type 'a key = 'a Key.t and type ('key, 'map) value = unit) : \u000A HETEROGENEOUS_SET\u000A with type 'a elt = 'a Key.t\u000A and type 'a BaseMap.t = 'a NODE.t

Create an heterogeneous set with a custom NODE.

Hash-consed maps and sets

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:

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.

module MakeHashconsedMap (Key : KEY) (Value : HASHED_VALUE) () : sig ... end

Hash-consed version of MAP. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed maps.

module MakeHashconsedSet (Key : KEY) () : sig ... end

Hash-consed version of SET. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed sets.

module MakeHashconsedHeterogeneousSet\u000A (Key : HETEROGENEOUS_KEY)\u000A () : \u000A sig ... end

Hash-consed version of HETEROGENEOUS_SET. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed sets.

module MakeHashconsedHeterogeneousMap\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_HASHED_VALUE)\u000A () : \u000A sig ... end

Hash-consed version of HETEROGENEOUS_MAP. See Hash-consed maps and sets for the differences between hash-consed and non hash-consed maps.

Some implementations of NODE

We provide a few different implementations of NODE, they can be used with the MakeCustomMap, MakeCustomSet, MakeCustomHeterogeneousMap and MakeCustomHeterogeneousSet functors.

Basic nodes

module SimpleNode\u000A (Key : sig ... end)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

This module is such that 'map t = 'map view. This is the node used in MakeHeterogeneousMap and MakeMap.

module NodeWithId\u000A (Key : sig ... end)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A NODE_WITH_ID\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hash-tables.

module SetNode\u000A (Key : sig ... end) : \u000A NODE with type 'a key = 'a Key.t and type ('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.

Weak nodes

module WeakNode\u000A (Key : sig ... end)\u000A (Value : HETEROGENEOUS_VALUE) : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

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

module WeakSetNode\u000A (Key : sig ... end) : \u000A NODE with type 'a key = 'a Key.t and type ('key, 'map) value = unit

Both a WeakNode and a SetNode, useful to implement Weak sets.

Hashconsed nodes

module HashconsedNode\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : HETEROGENEOUS_HASHED_VALUE)\u000A () : \u000A HASH_CONSED_NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

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.

module HashconsedSetNode\u000A (Key : HETEROGENEOUS_KEY)\u000A () : \u000A HASH_CONSED_NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = unit

Both a HashconsedNode and a SetNode.

"} \ 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.

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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":"

VALUE parameter for Hash-consed maps and sets, as hash-consing requires hashing and comparing values.

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.

","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

val hash : 'map t -> int

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 : 'a t -> '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 : 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:

"} \ 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.

See Hash-consed maps and sets for a details on strengths and limits of hash-consing.

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

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.

val equal : 'a t -> 'a t -> bool

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.

val compare : 'a t -> 'a t -> int

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":"

In order to build Hash-consed maps and sets, we need to be able to hash and compare values.

This is the heterogeneous version of HASHED_VALUE, used to specify a value for heterogeneous maps (in MakeHashconsedHeterogeneousMap). A default implementation is provided in HeterogeneousHashedValue, using Hashtbl.hash as hash function and physical equality as polyeq.

","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

val hash : ('key, 'map) t -> int

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:

"} \ 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.

val to_int : 'key t -> int

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.

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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_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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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_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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

","content":"

The main changes from SET are:

type 'a elt

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt

Existential wrapper for set elements.

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> any_elt

The minimal element if non empty, according to the unsigned order on elements.

val unsigned_max_elt : t -> any_elt

The maximal element if non empty, according to the unsigned order on elements.

val pop_unsigned_minimum : t -> (any_elt * t) option

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 elements.

val pop_unsigned_maximum : t -> (any_elt * t) option

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 elements.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in the unsigned order of KEY.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in the unsigned order of KEY.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in the unsigned order of KEY.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

to_list s returns the elements of s as a list, 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.

val to_int : t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, 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-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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b value) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b value) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c value option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value value -> ('a, 'map2) Map2.value -> 'value value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key ->\u000A 'map1 value option ->\u000A ('a, 'map2) Map2.value ->\u000A 'map1 value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. key -> 'map1 value -> ('a, 'map2) Map2.value -> 'map1 value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b value) snd

Underlying basemap, for cross map/set operations

Basic functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val unsigned_min_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is minimal (in the unsigned representation of integers); O(log n) complexity.

val unsigned_max_binding : 'a t -> key * 'a value

Returns the (key,value) pair where Key.to_int key is maximal (in the unsigned representation of integers); O(log n) complexity.

val singleton : key -> 'a value -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map. O(n) complexity.

val is_singleton : 'a t -> (key * 'a value) option

is_singleton m is Some (k,v) iff m is singleton k v.

val find : key -> 'a t -> 'a value

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a value option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true if and only if key is bound in map. O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

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 : 'a t -> (key * 'a value * 'a t) 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 : 'a t -> (key * 'a value * 'a t) 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.

val insert : key -> ('a value option -> 'a value) -> 'a t -> 'a t

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 value option -> 'a value option) -> 'a t -> 'a t

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 : key -> 'a value -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a value option * 'a t

split key map splits the map into:

Uses the unsigned order on KEY.to_int.

val iter : (key -> 'a value -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold : (key -> 'a value -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing unsigned order of KEY.to_int.

val fold_on_nonequal_inter : \u000A (key -> 'a value -> 'a value -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\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.

val fold_on_nonequal_union : \u000A (key -> 'a value option -> 'a value option -> 'acc -> 'acc) ->\u000A 'a t ->\u000A 'a t ->\u000A 'acc ->\u000A 'acc

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.

val filter : (key -> 'a value -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing unsigned order of KEY.to_int.

val for_all : (key -> 'a value -> bool) -> 'a t -> bool

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).

val map : ('a value -> 'a value) -> 'a t -> 'a t

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.

val map_no_share : ('a value -> 'b value) -> 'a t -> 'b t

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.

val mapi : (key -> 'a value -> 'a value) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a value -> 'b value) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a value -> 'a value option) -> 'a t -> 'a t

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 -> 'a value -> 'b value option) -> 'a t -> 'b t

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 -> 'a value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 value -> 'b value -> bool) ->\u000A 'a t ->\u000A 'b t ->\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 value -> 'a value -> bool) ->\u000A 'a t ->\u000A 'a t ->\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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'a value -> 'a value) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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 -> 'a value -> 'b value -> 'c value) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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 -> 'a value -> 'a value -> 'a value option) ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a value option -> 'b value option -> 'c value option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps. Map2 must use the same KEY.to_int function.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a value -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> (key * 'a value) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : (key * 'a value) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a value) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a value) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a value) list

to_list m returns the bindings of m as a list, 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-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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val to_int : 'a t -> int

Unique number for each node.

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

Where the order is given by the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch or if f.f returns false.

It is useful to implement equality on maps:

# let equal m1 m2 = MyMap.reflexive_same_domain_for_all2\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

Assumes f.f is reflexive, i.e. f.f k v v = true to skip calls to equal subtrees. Calls f.f in ascending unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, 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-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.

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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.

type ('map1, 'map2) polyupdate_multiple_inter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    Same constraints as branch:

    • branching_bit contains only one bit set; the corresponding mask is (branching_bit - 1).
    • prefix is normalized: the bits below the branching_bit are set to zero (i.e. prefix & (branching_bit - 1) = 0).
    • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
    • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).
    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val unsigned_min_binding : 'a t -> 'a key_value_pair

unsigned_min_binding m is minimal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val unsigned_max_binding : 'a t -> 'a key_value_pair

unsigned_max_binding m is maximal binding KeyValue(k,v) of the map, using the unsigned order on KEY.to_int.

  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t

Create a map with a single binding.

val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value

find key map returns the value associated with key in map if present.

  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

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 : 'map t -> ('map key_value_pair * 'map t) 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 : 'map t -> ('map key_value_pair * 'map t) 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.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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 the unsigned order on KEY.to_int.

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the unsigned order on KEY.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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 = {
  1. f : 'a. 'a key -> ('a, 'map) value -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold_on_nonequal_inter : \u000A ('acc, 'map) polyfold2 ->\u000A 'map t ->\u000A 'map t ->\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.

type ('acc, 'map) polyfold2_union = {
  1. f : 'a. 'a key ->\u000A ('a, 'map) value option ->\u000A ('a, 'map) value option ->\u000A 'acc ->\u000A 'acc;
}
val fold_on_nonequal_union : \u000A ('acc, 'map) polyfold2_union ->\u000A 'map t ->\u000A 'map t ->\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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the unsigned order of KEY.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the unsigned order of KEY.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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 unsigned order of KEY.to_int. Exits early if the domains mismatch.

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

idempotent_union f map1 map2 returns a map whose keys is the union of the keys of map1 and map2. f.f is used to combine the values of keys mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

idempotent_inter f map1 map2 returns a map whose keys is the intersection of the keys of map1 and map2. f.f is used to combine the values a key is mapped in both maps.

Assumes f.f idempotent (i.e. f key value value == value) f.f is called in the unsigned order of KEY.to_int. f.f is never called on physically equal values. Preserves physical equality as much as possible. Complexity is O(log(n)*Delta) where Delta is the number of different keys between map1 and map2.

val nonidempotent_inter_no_share : \u000A ('a, 'b, 'c) polyinter ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing unsigned order of KEY.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing unsigned order of KEY.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing unsigned order of KEY.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

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.

","content":"
type elt

The type of elements of the set

type key = elt

Alias for the type of elements, for cross-compatibility with maps

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The set type

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

cardinal set is the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val unsigned_min_elt : t -> elt

The minimal element (according to the unsigned order on KEY.to_int) if non empty.

val unsigned_max_elt : t -> elt

The maximal element (according to the unsigned order on KEY.to_int) if non empty.

val pop_unsigned_minimum : t -> (elt * t) option

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.

val pop_unsigned_maximum : t -> (elt * t) option

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.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in the unsigned order of KEY.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in the unsigned order of KEY.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in the unsigned order of KEY.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing unsigned order of KEY.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing unsigned order of KEY.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing unsigned order of KEY.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

to_list s returns the elements of s as a list, 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-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.

","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.

This library was written by Matthieu Lemerre, then further improved by Dorian Lesbre, as part of the Codex semantics library, developed at CEA List.

","content":"

Installation

This library can be installed with opam:

opam install patricia-tree

Alternatively, you can clone the source repository and install with dune:

git clone git@github.com:codex-semantics-library/patricia-tree.git\u000Acd patricia-tree\u000Aopan install . --deps-only\u000Adune build -p patricia-tree\u000Adune install\u000A# To build documentation\u000Aopam install . --deps-only --with-doc\u000Adune build @doc

Features

Quick overview

Functors

This library contains a single module, PatriciaTree. The functors used to build maps and sets are the following:

Interfaces

Here is a brief overview of the various module types of our library:

Examples

Homogeneous map

Here is a small example of a non-generic map:

  1. Start by creating a key module:

    module IntKey : PatriciaTree.KEY with type t = int = struct\u000A  type t = int\u000A  let to_int x = x\u000Aend
  2. 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);;
  3. 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)

    # IMap.find 1 map;;\u000A- : string = "hello"\u000A# IMap.cardinal map;;\u000A- : int = 3
  4. 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.

    # let map2 =\u000A    IMap.idempotent_inter_filter (fun _key _l _r -> None)\u000A      (IMap.add 4 "something" map)\u000A      (IMap.add 5 "something else" map);;\u000Aval map2 : string IMap.t = <abstr>\u000A# map == map2;;\u000A- : bool = true

    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:

    # let map3 = IMap.remove 2 map;;\u000Aval map3 : string IMap.t = <abstr>\u000A# IMap.add 2 (IMap.find 2 map) map3 == map;;\u000A- : bool = false

    If you want to maintain full physical equality (and thus get cheap equality test between maps), use the provided hash-consed maps and sets.

  5. Our library also allows cross map/set operations through the WithForeign functors:

    module CrossOperations = IMap.WithForeign(ISet.BaseMap)

    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.

  1. 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
  2. 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)
  3. You can now use this as you would any other dependent map:

    # let 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\u000Aval map : unit EMap.t = <abstr>\u000A# EMap.find (G_Const_Bool false) map;;\u000A- : bool = false\u000A# EMap.find (G_Const_Int 5) map;;\u000A- : int = 5\u000A# EMap.cardinal map;;\u000A- : int = 4
  4. 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.

For more details about this issue, see the OCaml discourse discussion.

Comparison to other OCaml libraries

ptmap and ptset

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:

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:

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Combination with other kinds of maps.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value -> ('a, 'map2) Map2.value -> 'value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key -> 'map1 option -> ('a, 'map2) Map2.value -> 'map1 option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. key -> 'map1 -> ('a, 'map2) Map2.value -> 'map1 option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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":"
type t

The type of keys

val to_int : t -> int

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.

","content":"

Types

type 'a key = Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) snd

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create a Homogeneous Map with a custom NODE.

","content":"

Parameters

module Key : KEY
module NODE : NODE with type 'a key = Key.t and type ('key, 'map) value = ('key, 'map) snd

Signature

type key = Key.t

The type of keys.

type 'm t = 'm NODE.t

A map from keys to values of type 'a.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b) snd

Underlying basemap, for cross map/set operations

Basice functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val min_binding : 'a t -> key * 'a

Returns the (key,value) where Key.to_int key is minimal (in unsigned representation of integers); O(log n) complexity.

val max_binding : 'a t -> key * 'a

Returns the (key,value) where Key.to_int key is maximal; O(log n) complexity.

val singleton : key -> 'a -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map

val is_singleton : 'a t -> (key * 'a) option

is_singleton m is Some (k,v) iff m is singleton k v

val find : key -> 'a t -> 'a

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'a t -> (key * 'a * 'a t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'a t -> (key * 'a * 'a t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : key -> ('a option -> 'a) -> 'a t -> 'a t

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) -> 'a t -> 'a t

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 : key -> 'a -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a option * 'a t

split key map splits the map into:

val iter : (key -> 'a -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing order of keys.

val fold : (key -> 'a -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing order of keys.

val filter : (key -> 'a -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing number of keys

val for_all : (key -> 'a -> bool) -> 'a t -> bool

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).

val map : ('a -> 'a) -> 'a t -> 'a t

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.

val map_no_share : ('a -> 'b) -> 'a t -> 'b t

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 order of keys.

val mapi : (key -> 'a -> 'a) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a -> 'b) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a -> 'a option) -> 'a t -> 'a t

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) -> 'a t -> 'b t

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 'a t ->\u000A 'a t ->\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 'a t ->\u000A 'b t ->\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 'a t ->\u000A 'a t ->\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) -> 'a t -> 'a t -> 'a t

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) -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a option -> 'b option -> 'c option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> (key * 'a) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : (key * 'a) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a) list

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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":"
type 'key t

The type of generic/heterogeneous keys

val to_int : 'key t -> int

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

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Create an Heterogeneous map with a custom NODE.

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 main changes from MAP are:

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : VALUE
module NODE : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

Signature

include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t\u000A with type 'm t = 'm NODE.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t\u000A with type 'm t = 'm NODE.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

The type of value, which depends on the type of the key and the type of the map.

type 'm t = 'm NODE.t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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":"
type 'key t

The type of generic/heterogeneous keys

val to_int : 'key t -> int

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

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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 main changes from MAP are:

","content":"

Parameters

module Key : HETEROGENEOUS_KEY
module Value : VALUE

Signature

include BASE_MAP\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t
include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('k, 'm) value = ('k, 'm) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('k, 'm) value = ('k, 'm) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
type 'key t

The type of generic/heterogeneous keys

val to_int : 'key t -> int

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

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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.

","content":"

Parameters

module Key : HETEROGENEOUS_KEY

Signature

The main changes from SET are:

type 'a elt = 'a Key.t

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt
    (*

    Existential wrapper for keys

    *)

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val min_elt : t -> any_elt

The minimal element if non empty.

val max_elt : t -> any_elt

The maximal element if non empty.

val pop_minimum : t -> (any_elt * t) option

pop_minimum s is Some (elt, s') where elt = min_elt s and s' = remove elt s if s is non empty.

val pop_maximum : t -> (any_elt * t) option

pop_maximum s is Some (elt, s') where elt = max_elt s and s' = remove elt s if s is non empty.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in order of Key.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in order of Key.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in order of Key.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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 order of Key.to_int

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing order of Key.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing order of Key.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Combination with other kinds of maps.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value -> ('a, 'map2) Map2.value -> 'value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key -> 'map1 option -> ('a, 'map2) Map2.value -> 'map1 option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. key -> 'map1 -> ('a, 'map2) Map2.value -> 'map1 option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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":"
type t

The type of keys

val to_int : t -> int

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":"

Parameters

module Key : KEY

Signature

type key = Key.t

The type of keys.

type 'a t

A map from keys to values of type 'a.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b) snd

Underlying basemap, for cross map/set operations

Basice functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val min_binding : 'a t -> key * 'a

Returns the (key,value) where Key.to_int key is minimal (in unsigned representation of integers); O(log n) complexity.

val max_binding : 'a t -> key * 'a

Returns the (key,value) where Key.to_int key is maximal; O(log n) complexity.

val singleton : key -> 'a -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map

val is_singleton : 'a t -> (key * 'a) option

is_singleton m is Some (k,v) iff m is singleton k v

val find : key -> 'a t -> 'a

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'a t -> (key * 'a * 'a t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'a t -> (key * 'a * 'a t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : key -> ('a option -> 'a) -> 'a t -> 'a t

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) -> 'a t -> 'a t

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 : key -> 'a -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a option * 'a t

split key map splits the map into:

val iter : (key -> 'a -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing order of keys.

val fold : (key -> 'a -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing order of keys.

val filter : (key -> 'a -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing number of keys

val for_all : (key -> 'a -> bool) -> 'a t -> bool

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).

val map : ('a -> 'a) -> 'a t -> 'a t

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.

val map_no_share : ('a -> 'b) -> 'a t -> 'b t

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 order of keys.

val mapi : (key -> 'a -> 'a) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a -> 'b) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a -> 'a option) -> 'a t -> 'a t

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) -> 'a t -> 'b t

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 'a t ->\u000A 'a t ->\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 'a t ->\u000A 'b t ->\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 'a t ->\u000A 'a t ->\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) -> 'a t -> 'a t -> 'a t

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) -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a option -> 'b option -> 'c option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> (key * 'a) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : (key * 'a) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a) list

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
type t

The type of keys

val to_int : t -> int

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":"

Parameters

module Key : KEY

Signature

type elt = Key.t

The type of elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

Basic functions

type key = elt

Alias for the type of elements, for cross-compatibility with maps

type t = unit BaseMap.t

The set type

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val min_elt : t -> elt

The minimal element if non empty.

val max_elt : t -> elt

The maximal element if non empty.

val pop_minimum : t -> (elt * t) option

pop_minimum s is Some (elt, s') where elt = min_elt s and s' = remove elt s if s is non empty.

val pop_maximum : t -> (elt * t) option

pop_maximum s is Some (elt, s') where elt = max_elt s and s' = remove elt s if s is non empty.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in order of Key.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in order of Key.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in order of Key.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing order of Key.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing order of Key.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing order of Key.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

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.

","content":"

Parameters

module Key : sig ... end
module Value : VALUE

Signature

include NODE\u000A with type 'a key = 'a Key.t\u000A with type ('key, 'map) value = ('key, 'map) Value.t

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val get_id : 'a t -> int
"} \ 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.

","content":"

Parameters

module Key : sig ... end

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"

Parameters

module Key : sig ... end
module Value : VALUE

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"

Parameters

module Key : sig ... end
module Value : VALUE

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = ('key, 'map) Value.t

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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.

","content":"

Parameters

module Key : sig ... end

Signature

Types

type 'a key = 'a Key.t

The type of keys.

type ('key, 'map) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"
type ('a, 'map) t = ('a, 'map) snd
"} \ 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 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.

","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.

type intkey
type mask

Nodes

module type NODE = sig ... end

This module explains how a node is stored in memory, with functions to create and view nodes.

module type NODE_WITH_ID = sig ... end

Associate a unique number to each node.

Map signatures

Base map

module type BASE_MAP = sig ... end

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

module type HETEROGENEOUS_MAP = sig ... end

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.

module type HETEROGENEOUS_SET = sig ... end

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

Homogeneous maps and sets

Same as above, but simple interfaces for non-generic keys

module type SET = sig ... end

Signature for sets implemented using Patricia trees. Most of this interface should be shared with Stdlib.Set.S.

type (_, 'b) snd =
  1. | Snd of '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.

This is due to a bug in the typechecker, more info on the OCaml discourse post.

module type MAP = sig ... end

The signature for maps with a single type for keys and values. Most of this interface should be shared with Stdlib.Set.S.

Keys

Keys are the functor arguments used to build the maps.

module type KEY = sig ... end

The signature of keys when they are all of the same type.

type (_, _) cmp =
  1. | Eq : ('a, 'a) cmp
  2. | Diff : ('a, 'b) cmp

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 HETEROGENEOUS_KEY = sig ... end

The signature of heterogeneous keys.

module type VALUE = sig ... end

The moodule type of values, which can be heterogeneous.

module HomogeneousValue : VALUE with type ('a, 'map) t = 'map

To use when the type of the value is the same (but the keys can still be heterogeneous).

module WrappedHomogeneousValue : VALUE with type ('a, 'map) t = ('a, 'map) snd

Functors

Homogeneous maps and sets

module MakeMap (Key : KEY) : MAP with type key = Key.t
module MakeSet (Key : KEY) : SET with type elt = Key.t

Heterogeneous maps and sets

module MakeHeterogeneousSet\u000A (Key : HETEROGENEOUS_KEY) : \u000A HETEROGENEOUS_SET with type 'a elt = 'a Key.t

A set containing different keys, very similar to SET, but with simple type elt being replaced by type constructor 'a elt.

module MakeHeterogeneousMap\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : VALUE) : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t

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.

module MakeCustom\u000A (Key : KEY)\u000A (NODE : \u000A NODE\u000A with type 'a key = Key.t\u000A and type ('key, 'map) value = ('key, 'map) snd) : \u000A MAP with type key = Key.t and type 'm t = 'm NODE.t

Create a Homogeneous Map with a custom NODE.

module MakeCustomHeterogeneous\u000A (Key : HETEROGENEOUS_KEY)\u000A (Value : VALUE)\u000A (NODE : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t) : \u000A HETEROGENEOUS_MAP\u000A with type 'a key = 'a Key.t\u000A and type ('k, 'm) value = ('k, 'm) Value.t\u000A and type 'm t = 'm NODE.t

Create an Heterogeneous map with a custom NODE.

Some implementations of NODE

module SimpleNode\u000A (Key : sig ... end)\u000A (Value : VALUE) : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

This module is such that 'map t = 'map view.

module NodeWithId\u000A (Key : sig ... end)\u000A (Value : VALUE) : \u000A NODE_WITH_ID\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

Here, nodes also contain a unique id, e.g. so that they can be used as keys of maps or hashtables.

module SetNode\u000A (Key : sig ... end) : \u000A NODE with type 'a key = 'a Key.t and type ('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).

module WeakNode\u000A (Key : sig ... end)\u000A (Value : VALUE) : \u000A NODE\u000A with type 'a key = 'a Key.t\u000A and type ('key, 'map) value = ('key, 'map) Value.t

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

module WeakSetNode\u000A (Key : sig ... end) : \u000A NODE with type 'a key = 'a Key.t and type ('key, 'map) value = unit

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:

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

The signature of heterogeneous keys.

","content":"
type 'key t

The type of generic/heterogeneous keys

val to_int : 'key t -> int

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

val polyeq : 'a t -> 'b t -> ('a, 'b) cmp

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type 'a key = 'a elt with type (_, _) value = unit
include NODE with type 'a key = 'a elt with type (_, _) value = unit

Types

type 'a key = 'a elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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.

","content":"

The main changes from SET are:

type 'a elt

Elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type 'a key = 'a elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

type t = unit BaseMap.t

The type of our set

type 'a key = 'a elt

Alias for elements, for compatibility with other PatriciaTrees

type any_elt =
  1. | Any : 'a elt -> any_elt
    (*

    Existential wrapper for keys

    *)

Basic functions

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : 'a elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : 'a elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : 'a elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> any_elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : 'a elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val min_elt : t -> any_elt

The minimal element if non empty.

val max_elt : t -> any_elt

The maximal element if non empty.

val pop_minimum : t -> (any_elt * t) option

pop_minimum s is Some (elt, s') where elt = min_elt s and s' = remove elt s if s is non empty.

val pop_maximum : t -> (any_elt * t) option

pop_maximum s is Some (elt, s') where elt = max_elt s and s' = remove elt s if s is non empty.

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

val split : 'a elt -> t -> t * bool * t

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.

Iterators

type polyiter = {
  1. f : 'a. 'a elt -> unit;
}
val iter : polyiter -> t -> unit

iter f set calls f.f on all elements of set, in order of Key.to_int.

type polypredicate = {
  1. f : 'a. 'a elt -> bool;
}
val filter : polypredicate -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f.f. f.f is called in order of Key.to_int.

val for_all : polypredicate -> t -> bool

for_all f set is true if f.f is true on all elements of set. Short-circuits on first false. f.f is called in order of Key.to_int.

type 'acc polyfold = {
  1. f : 'a. 'a elt -> 'acc -> 'acc;
}
val fold : 'acc polyfold -> t -> 'acc -> 'acc

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 order of Key.to_int

type polypretty = {
  1. f : 'a. Stdlib.Format.formatter -> 'a elt -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A polypretty ->\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

Conversion functions

val to_seq : t -> any_elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing order of Key.to_int

val to_rev_seq : t -> any_elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing order of Key.to_int

val add_seq : any_elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : any_elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : any_elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> any_elt list

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.

","content":"
type t

The type of keys

val to_int : t -> int

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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b) snd
include NODE\u000A with type 'a t = 'a t\u000A with type _ key = key\u000A with type ('a, 'b) value = ('a, 'b) snd

Types

type _ key = key

The type of keys.

type ('a, 'b) value = ('a, 'b) snd

The type of value, which depends on the type of the key and the type of the map.

type 'a t = 'a t

The type of the map, which is parameterized by a type.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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":"
include NODE with type _ key = key

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Combination with other kinds of maps.

","content":"

Parameters

module Map2 : BASE_MAP with type _ key = key

Signature

type ('b, 'c) polyfilter_map_foreign = {
  1. f : 'a. key -> ('a, 'b) Map2.value -> 'c option;
}
val filter_map_no_share : ('b, 'c) polyfilter_map_foreign -> 'b Map2.t -> 'c t

Like filter_map_no_share, but takes another map.

type ('value, 'map2) polyinter_foreign = {
  1. f : 'a. 'a Map2.key -> 'value -> ('a, 'map2) Map2.value -> 'value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like nonidempotent_inter, but takes another map as an argument.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. key -> 'map1 option -> ('a, 'map2) Map2.value -> 'map1 option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. key -> 'map1 -> ('a, 'map2) Map2.value -> 'map1 option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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.

","content":"
type key

The type of keys.

type 'a t

A map from keys to values of type 'a.

module BaseMap : \u000A HETEROGENEOUS_MAP\u000A with type 'a t = 'a t\u000A and type _ key = key\u000A and type ('a, 'b) value = ('a, 'b) snd

Underlying basemap, for cross map/set operations

Basice functions

val empty : 'a t

The empty map.

val is_empty : 'a t -> bool

Test if a map is empty; O(1) complexity.

val min_binding : 'a t -> key * 'a

Returns the (key,value) where Key.to_int key is minimal (in unsigned representation of integers); O(log n) complexity.

val max_binding : 'a t -> key * 'a

Returns the (key,value) where Key.to_int key is maximal; O(log n) complexity.

val singleton : key -> 'a -> 'a t

singleton key value creates a map with a single binding, O(1) complexity.

val cardinal : 'a t -> int

The size of the map

val is_singleton : 'a t -> (key * 'a) option

is_singleton m is Some (k,v) iff m is singleton k v

val find : key -> 'a t -> 'a

Return an element in the map, or raise Not_found, O(log(n)) complexity.

val find_opt : key -> 'a t -> 'a option

Return an element in the map, or None, O(log(n)) complexity.

val mem : key -> 'a t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : key -> 'a t -> 'a t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'a t -> (key * 'a * 'a t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'a t -> (key * 'a * 'a t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : key -> ('a option -> 'a) -> 'a t -> 'a t

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) -> 'a t -> 'a t

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 : key -> 'a -> 'a t -> 'a t

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 : key -> 'a t -> 'a t * 'a option * 'a t

split key map splits the map into:

val iter : (key -> 'a -> unit) -> 'a t -> unit

Iterate on each (key,value) pair of the map, in increasing order of keys.

val fold : (key -> 'a -> 'acc -> 'acc) -> 'a t -> 'acc -> 'acc

Fold on each (key,value) pair of the map, in increasing order of keys.

val filter : (key -> 'a -> bool) -> 'a t -> 'a t

Returns the submap containing only the key->value pairs satisfying the given predicate. f is called in increasing number of keys

val for_all : (key -> 'a -> bool) -> 'a t -> bool

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).

val map : ('a -> 'a) -> 'a t -> 'a t

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.

val map_no_share : ('a -> 'b) -> 'a t -> 'b t

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 order of keys.

val mapi : (key -> 'a -> 'a) -> 'a t -> 'a t

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.

val mapi_no_share : (key -> 'a -> 'b) -> 'a t -> 'b t

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.

val filter_map : (key -> 'a -> 'a option) -> 'a t -> 'a t

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) -> 'a t -> 'b t

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 'a t ->\u000A 'a t ->\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 'a t ->\u000A 'b t ->\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 'a t ->\u000A 'a t ->\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) -> 'a t -> 'a t -> 'a t

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) -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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 'a t ->\u000A 'a t ->\u000A 'a t

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.

val slow_merge : \u000A (key -> 'a option -> 'b option -> 'c option) ->\u000A 'a t ->\u000A 'b t ->\u000A 'c t

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.

val disjoint : 'a t -> 'a t -> bool
module WithForeign (Map2 : BASE_MAP with type _ key = key) : sig ... end

Combination with other kinds of maps.

val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A (Stdlib.Format.formatter -> key -> 'a -> unit) ->\u000A Stdlib.Format.formatter ->\u000A 'a t ->\u000A unit

Pretty prints all bindings of the map. pp_sep is called once between each binding pair and defaults to Format.pp_print_cut.

Conversion functions

val to_seq : 'a t -> (key * 'a) Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> (key * 'a) Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : (key * 'a) Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : (key * 'a) Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : (key * 'a) list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> (key * 'a) list

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

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":"

Associate a unique number to each node.

","content":"
include NODE

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

val get_id : 'a t -> int
"} \ 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":"
include NODE with type 'a key = 'a key

Types

type 'a key = 'a 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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
val max_binding : 'a t -> 'a key_value_pair
val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

split key map splits the map into:

type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\u000A bool

reflexive_same_domain_for_all2 f m1 m2 is true if and only if

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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\u000A bool

reflexive_subset_domain_for_all2 f m1 m2 is true if and only if

type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

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":"

Operation with maps/set of different types

","content":"

Parameters

module Map2 : BASE_MAP with type 'a key = 'a key

Signature

type ('map1, 'map2) polyinter_foreign = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value;
}
val nonidempotent_inter : \u000A ('a, 'b) polyinter_foreign ->\u000A 'a t ->\u000A 'b Map2.t ->\u000A 'a t

Like BASE_MAP.idempotent_inter. Tries to preserve physical equality on the first argument when possible.

type ('map2, 'map1) polyfilter_map_foreign = {
  1. f : 'a. 'a key -> ('a, 'map2) Map2.value -> ('a, 'map1) value option;
}
val filter_map_no_share : \u000A ('map2, 'map1) polyfilter_map_foreign ->\u000A 'map2 Map2.t ->\u000A 'map1 t

Like BASE_MAP.filter_map_no_share, but allows to transform a foreigh map into the current one.

type ('map1, 'map2) polyupdate_multiple = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple ->\u000A 'a t ->\u000A 'a t

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 = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) Map2.value ->\u000A ('a, 'map1) value option;
}
val update_multiple_from_inter_with_foreign : \u000A 'b Map2.t ->\u000A ('a, 'b) polyupdate_multiple_inter ->\u000A 'a t ->\u000A 'a t

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 main changes from MAP are:

","content":"
include BASE_MAP with type _ key = elt with type (_, _) value = unit
include NODE with type _ key = elt with type (_, _) value = unit

Types

type _ key = elt

The type of keys.

type (_, _) value = unit

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.

Constructors: build values

val empty : 'map t

The empty map

val leaf : 'key key -> ('key, 'map) value -> 'map t

A singleton leaf, similar to BASE_MAP.singleton

val branch : \u000A prefix:intkey ->\u000A branching_bit:mask ->\u000A tree0:'map t ->\u000A tree1:'map t ->\u000A 'map t

A branch node. This shouldn't be called externally unless you know what you're doing! Doing so could easily break the data structure's invariants.

When called, it assumes that:

  • Neither tree0 nor tree1 should be empty.
  • branching_bit should have a single bit set
  • prefix should be normalized (bits below branching_bit set to zero)
  • All elements of tree0 should have their to_int start by prefix followed by 0 at position branching_bit).
  • All elements of tree1 should have their to_int start by prefix followed by 0 at position branching_bit).

Destructors: access the value

type 'map view = private
  1. | Empty : 'map view
    (*

    Can happen only at the toplevel: there is no empty interior node.

    *)
  2. | Branch : {
    1. prefix : intkey;
    2. branching_bit : mask;
    3. tree0 : 'map t;
    4. tree1 : 'map t;
    } -> 'map view
    (*

    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).

    *)
  3. | Leaf : {
    1. key : 'key key;
    2. value : ('key, 'map) value;
    } -> 'map view
    (*

    A key -> value mapping.

    *)

This makes the map nodes accessible to the pattern matching algorithm; this corresponds 1:1 to the SimpleNode implementation. This just needs to be copy-and-pasted for every node type.

val is_empty : 'map t -> bool

Check if the map is empty. Should be constant time.

val view : 'a t -> 'a view

Convert the map to a view. Should be constant time.

type 'map key_value_pair =
  1. | KeyValue : 'a key * ('a, 'map) value -> 'map key_value_pair

Existential wrapper for the 'a parameter in a 'a key, ('a,'map) value pair

Basic functions

val min_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val max_binding : 'a t -> 'a key_value_pair
  • raises Not_found

    if the map is empty

val singleton : 'a key -> ('a, 'b) value -> 'b t
val cardinal : 'a t -> int

The size of the map, O(n) complexity

val is_singleton : 'a t -> 'a key_value_pair option

is_singleton m returns Some(KeyValue(k,v)) if and only if m contains a unique binding k->v.

val find : 'key key -> 'map t -> ('key, 'map) value
  • raises Not_found

    if key is absent from map

val find_opt : 'key key -> 'map t -> ('key, 'map) value option

Same as find, but returns None for Not_found

val mem : 'key key -> 'map t -> bool

mem key map returns true iff key is bound in map, O(log(n)) complexity.

val remove : 'key key -> 'map t -> 'map t

Returns a map with the element removed, O(log(n)) complexity. Returns a physically equal map if the element is absent.

val pop_minimum : 'map t -> ('map key_value_pair * 'map t) option

pop_minimum m returns None if is_empty m, or Some(key,value,m') where (key,value) = min_binding m and m' = remove m key. O(log(n)) complexity.

val pop_maximum : 'map t -> ('map key_value_pair * 'map t) option

pop_maximum m returns None if is_empty m, or Some(key,value,m') where (key,value) = max_binding m and m' = remove m key. O(log(n)) complexity.

val insert : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value) ->\u000A 'map t ->\u000A 'map t

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 : \u000A 'a key ->\u000A (('a, 'map) value option -> ('a, 'map) value option) ->\u000A 'map t ->\u000A 'map t

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 : 'key key -> ('key, 'map) value -> 'map t -> 'map t

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 : 'key key -> 'map t -> 'map t * ('key, 'map) value option * 'map t

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.
type 'map polyiter = {
  1. f : 'a. 'a key -> ('a, 'map) value -> unit;
}
val iter : 'map polyiter -> 'map t -> unit

iter f m calls f.f on all bindings of m, in the order given by Key.to_int

type ('acc, 'map) polyfold = {
  1. f : 'a. 'a key -> ('a, 'map) value -> 'acc -> 'acc;
}
val fold : ('acc, 'map) polyfold -> 'map t -> '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.

type 'map polypredicate = {
  1. f : 'a. 'a key -> ('a, 'map) value -> bool;
}
val filter : 'map polypredicate -> 'map t -> 'map t

filter f m returns the submap of m containing the bindings k->v such that f.f k v = true. f.f is called in the order given by Key.to_int

val for_all : 'map polypredicate -> 'map t -> bool

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).

type ('map1, 'map2) polymap = {
  1. f : 'a. ('a, 'map1) value -> ('a, 'map2) value;
}
val map : ('map, 'map) polymap -> 'map t -> 'map t
val map_no_share : ('map1, 'map2) polymap -> 'map1 t -> 'map2 t

map f m and map_no_share f m replace all bindings (k,v) by (k, f.f v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polymapi = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value;
}
val mapi : ('map, 'map) polymapi -> 'map t -> 'map t
val mapi_no_share : ('map1, 'map2) polymapi -> 'map1 t -> 'map2 t

mapi f m and mapi_no_share f m replace all bindings (k,v) by (k, f.f k v). Bindings are examined in the order given by Key.to_int.

type ('map1, 'map2) polyfilter_map = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value option;
}
val filter_map : ('map, 'map) polyfilter_map -> 'map t -> 'map t
val filter_map_no_share : ('map1, 'map2) polyfilter_map -> 'map1 t -> 'map2 t

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 = {
  1. f : 'a. Stdlib.Format.formatter -> 'a key -> ('a, 'map) value -> unit;
}
val pretty : \u000A ?pp_sep:(Stdlib.Format.formatter -> unit -> unit) ->\u000A 'map polypretty ->\u000A Stdlib.Format.formatter ->\u000A 'map t ->\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 = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> bool;
}
val reflexive_same_domain_for_all2 : \u000A ('map, 'map) polysame_domain_for_all2 ->\u000A 'map t ->\u000A 'map t ->\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 'map1 t ->\u000A 'map2 t ->\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 'map t ->\u000A 'map t ->\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.
type ('map1, 'map2, 'map3) polyunion = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_union : ('a, 'a, 'a) polyunion -> 'a t -> 'a t -> 'a t

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.

type ('map1, 'map2, 'map3) polyinter = {
  1. f : 'a. 'a key -> ('a, 'map1) value -> ('a, 'map2) value -> ('a, 'map3) value;
}
val idempotent_inter : ('a, 'a, 'a) polyinter -> 'a t -> 'a t -> 'a t

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 'a t ->\u000A 'b t ->\u000A 'c t

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

type ('map1, 'map2, 'map3) polyinterfilter = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value ->\u000A ('a, 'map2) value ->\u000A ('a, 'map3) value option;
}
val idempotent_inter_filter : \u000A ('a, 'a, 'a) polyinterfilter ->\u000A 'a t ->\u000A 'a t ->\u000A 'a t

idempotent_inter_filter f map1 map2 is the same as idempotent_inter but f.f can return None to remove a binding from the resutling map.

type ('map1, 'map2, 'map3) polymerge = {
  1. f : 'a. 'a key ->\u000A ('a, 'map1) value option ->\u000A ('a, 'map2) value option ->\u000A ('a, 'map3) value option;
}
val slow_merge : \u000A ('map1, 'map2, 'map3) polymerge ->\u000A 'map1 t ->\u000A 'map2 t ->\u000A 'map3 t

This is the same as Stdlib.Map.S.merge

val disjoint : 'a t -> 'a t -> bool

disjoint m1 m2 is true iff m1 and m2 have disjoint domains

Conversion functions

val to_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_seq m iterates the whole map, in increasing order of Key.to_int

val to_rev_seq : 'a t -> 'a key_value_pair Stdlib.Seq.t

to_rev_seq m iterates the whole map, in decreasing order of Key.to_int

val add_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t -> 'a t

add_seq s m adds all bindings of the sequence s to m in order.

val of_seq : 'a key_value_pair Stdlib.Seq.t -> 'a t

of_seq s creates a new map from the bindings of s. If a key is bound multiple times in s, the latest binding is kept

val of_list : 'a key_value_pair list -> 'a t

of_list l creates a new map from the bindings of l. If a key is bound multiple times in l, the latest binding is kept

val to_list : 'a t -> 'a key_value_pair list

to_list m returns the bindings of m as a list, in increasing order of Key.to_int

module WithForeign (Map2 : BASE_MAP with type 'a key = 'a key) : sig ... end

Operation with maps/set of different types

"} \ 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.

","content":"
type elt

The type of elements of the set

module BaseMap : \u000A HETEROGENEOUS_MAP with type _ key = elt and type (_, _) value = unit

Underlying basemap, for cross map/set operations

Basic functions

type key = elt

Alias for the type of elements, for cross-compatibility with maps

type t = unit BaseMap.t

The set type

val empty : t

The empty set

val is_empty : t -> bool

is_empty st is true if st contains no elements, false otherwise

val mem : elt -> t -> bool

mem elt set is true if elt is contained in set, O(log(n)) complexity.

val add : elt -> t -> t

add elt set adds element elt to the set. Preserves physical equality if elt was already present. O(log(n)) complexity.

val singleton : elt -> t

singleton elt returns a set containing a single element: elt

val cardinal : t -> int

the size of the set (number of elements), O(n) complexity.

val is_singleton : t -> elt option

is_singleton set is Some (Any elt) if set is singleton elt and None otherwise.

val remove : elt -> t -> t

remove elt set returns a set containing all elements of set except elt. Returns a value physically equal to set if elt is not present.

val min_elt : t -> elt

The minimal element if non empty.

val max_elt : t -> elt

The maximal element if non empty.

val pop_minimum : t -> (elt * t) option

pop_minimum s is Some (elt, s') where elt = min_elt s and s' = remove elt s if s is non empty.

val pop_maximum : t -> (elt * t) option

pop_maximum s is Some (elt, s') where elt = max_elt s and s' = remove elt s if s is non empty.

Iterators

val iter : (elt -> unit) -> t -> unit

iter f set calls f on all elements of set, in order of Key.to_int.

val filter : (elt -> bool) -> t -> t

filter f set is the subset of set that only contains the elements that satisfy f. f is called in order of Key.to_int.

val for_all : (elt -> bool) -> t -> bool

for_all f set is true if f is true on all elements of set. Short-circuits on first false. f is called in order of Key.to_int.

val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc

fold f set acc returns f elt_n (... (f elt_1 acc) ...), where elt_1, ..., elt_n are the elements of set, in increasing order of Key.to_int

val split : elt -> t -> t * bool * t

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

Functions on pairs of sets

val union : t -> t -> t

union a b is the set union of a and b, i.e. the set containing all elements that are either in a or b.

val inter : t -> t -> t

inter a b is the set intersection of a and b, i.e. the set containing all elements that are in both a or b.

val disjoint : t -> t -> bool

disjoint a b is true if a and b have no elements in common.

val equal : t -> t -> bool

equal a b is true if a and b contain the same elements.

val subset : t -> t -> bool

subset a b is true if all elements of a are also in b.

Conversion functions

val to_seq : t -> elt Stdlib.Seq.t

to_seq st iterates the whole set, in increasing order of Key.to_int

val to_rev_seq : t -> elt Stdlib.Seq.t

to_rev_seq st iterates the whole set, in decreasing order of Key.to_int

val add_seq : elt Stdlib.Seq.t -> t -> t

add_seq s st adds all elements of the sequence s to st in order.

val of_seq : elt Stdlib.Seq.t -> t

of_seq s creates a new set from the elements of s.

val of_list : elt list -> t

of_list l creates a new set from the elements of l.

val to_list : t -> elt list

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.

","content":"

Installation

This library can be installed with opam:

opam install patricia-tree

Alternatively, you can clone the source repository and install with dune:

git clone git@github.com:codex-semantics-library/patricia-tree.git\u000Aopam install . --deps-only\u000Acd patricia-tree\u000Adune build\u000Adune install\u000A# To build documentation\u000Aopam install odoc\u000Adune build @doc

Features

Quick overview

Functors

This library contains a single module, PatriciaTree. The functors used to build maps and sets are the following:

Interfaces

Here is a brief overview of the various module types of our library:

Examples

Homogeneous map

Here is a small example of a non-generic map:

(** 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.

For more details about this issue, see the OCaml discourse discussion.

Comparison to other OCaml libraries

ptmap and ptset

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:

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:

"} \ 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 -%} + {{shield.alt-text}} + {%- else -%} + {{shield.alt-text}} + {%- endif -%} + {% endfor %} +
diff --git a/_layouts/odoc.html b/_layouts/odoc.html new file mode 100644 index 0000000..c8337cf --- /dev/null +++ b/_layouts/odoc.html @@ -0,0 +1,86 @@ +--- +title: Codex API +layout: default +compress_html: blanklines +css: ["api", "pygments"] +--- + + + + +
+ {% comment %} ==== Breadcrumbs ==== {% endcomment %} + + + {% comment %} ==== Search bar ==== {% endcomment %} + + + + + {% comment %} ==== Main content ==== {% endcomment %} +
+
+ {% assign name = page.odoc.breadcrumbs.last.name %} + {% assign package = site.data.packages[page.package] %} + + {% if page.version != package.latest-version %} +

+ {% 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. +

+ {% endif %} + + {% unless name == "index" %} +

{{ package.name }} API - {{ name }}

+ {% endunless %} + + {{ page.odoc.preamble }} + + {{ page.odoc.content }} +
+
+
+
diff --git a/_layouts/vendor/compress.html b/_layouts/vendor/compress.html new file mode 100644 index 0000000..126e57d --- /dev/null +++ b/_layouts/vendor/compress.html @@ -0,0 +1,14 @@ +--- +# Jekyll layout that compresses HTML +# v3.1.0 +# http://jch.penibelst.de/ +# © 2014–2015 Anatol Broder +# MIT License +# +# With small edits to allow disabling/switching to blanklines mode via page/layout +# frontmatter (used namely in _layouts/odoc, as odoc generated pages are already +# compressed and use whitespace in their code blocks). +--- + +{% capture _LINE_FEED %} +{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" or layout.compress_html == "disabled" or page.compress_html == "disabled" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines or page.compress_html == "blanklines" or layout.compress_html == "blanklines" %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "" %}{% endif %}{% unless _pre_before contains "" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " ;; ;" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %}
Step Bytes
raw {{ content | size }}{% if _profile_endings %}
endings {{ _profile_endings }}{% endif %}{% if _profile_startings %}
startings {{ _profile_startings }}{% endif %}{% if _profile_comments %}
comments {{ _profile_comments }}{% endif %}{% if _profile_collapse %}
collapse {{ _profile_collapse }}{% endif %}{% if _profile_clippings %}
clippings {{ _profile_clippings }}{% endif %}
{% endif %}{% endif %} diff --git a/_plugins/odoc.rb b/_plugins/odoc.rb new file mode 100644 index 0000000..e999136 --- /dev/null +++ b/_plugins/odoc.rb @@ -0,0 +1,90 @@ +# Ruby plugin for odoc generated json files (by dune build @doc-json) +# Autodectects json files placed in _data/api +# Originally written by Allan Blanchard for Frama-C's website +# https://git.frama-c.com/pub/pub.frama-c.com +# +# This expects you place files generated by 'dune build @doc-json' +# from '_build/default/_doc/_html/' (note that this EXCLUDES the odoc package list page!) +# in '_data/api//' +# where '' has '.' replaced by '__' (Jekyll removes '.' in filenames) +# +# You also have to move the '_build/default/_doc/_html//db.js' file (generated by sherlodoc) +# to 'assets/js/db...js' +module OdocPlugin + class OdocPageGenerator < Jekyll::Generator + safe true + + def find_all_pages(hash) + results = {} + def iter(hash, path, results, depth) + if hash then + hash.each do |key, value| + if key == 'indexhtml' then + results[path] = value + elsif value.is_a? Hash + npath = path+[key] + if depth == 1 then + # Replace "__" in version folder name by "." + # This is required because Jekyll strips all "." from the data file names + version = key.gsub('__', '.') + npath = path+[version] + end + iter(value, npath, results, depth+1) + else + raise "Don't know what to do with value #{value}\n" + end + end + end + end + iter(hash, [], results, 0) + results + end + + def generate(site) + pages = find_all_pages(site.data['api']) + site.data["odoc_pages"] = [] + pages.each do |path, data| + page = OdocPage.new(site, path, data) + site.pages << page + site.data["odoc_pages"] << page + end + end + end + + class OdocPage < Jekyll::Page + def initialize(site, path, data) + @site = site + @base = site.source + @dir = "api/" + path.join('/') + @basename = 'index' + @ext = '.html' + @name = @basename + @ext + # We can get package and version from path thanks to our custom folder structure. + # 'dune build @doc-json' generates a tree rooted at package: + # (./package-name, ./package-name/module, ./package-name/index.html...) + # We added a version layer: + # (./package-name/vX.Y.Z/, ./package-name/vX.Y.Z/module, ./package-name/vX.Y.Z/index.html...) + # The page at ./package-name is manually written (See api folder), it should list all versions. + package = path[0] + version = path[1] + @data = { + 'odoc' => data, + 'layout' => 'odoc', + 'package' => package, + 'version' => version, + 'title' => data["breadcrumbs"][-1]["name"] + " - " + package + "." + version, + 'nav_exclude' => true, + 'search_exclude' => true, + } + # If the current version matches the package latest version + if path[1] == site.data["packages"][package]["latest-version"] then + # Add a redirect from /api/package/latest/path to this page + path_clone = [package] + ["latest"] + path[2..-1] + ["index.html"] + @data["redirect_from"] = "api/" + path_clone.join('/') + # Add the current page info to search + @data['content'] = data["preamble"] + data["content"] + @data['search_exclude'] = false + end + end + end +end diff --git a/_sass/color_schemes/myscheme.scss b/_sass/color_schemes/myscheme.scss index e92d585..f08b549 100644 --- a/_sass/color_schemes/myscheme.scss +++ b/_sass/color_schemes/myscheme.scss @@ -1,10 +1,10 @@ -// The variables are in _sass/support/_variables.scss and light.scss in the just-the-docs theme, and in +// The variables are in _sass/support/_variables.scss and light.scss in the just-the-docs theme, and in // See: https://just-the-docs.github.io/just-the-docs/docs/customization/#define-a-custom-scheme // http://www.georgduffner.at/ebgaramond/ $body-font-family: 'EB Garamond', serif; // https://iginomarini.com/fell/ //$body-font-family: 'IM Fell DW Pica', serif; // Also exists in small caps, see https://fonts.google.com/specimen/IM+Fell+DW+Pica?query=im+fell -// $root-font-size: 16px; +// $root-font-size: 16px; $body-line-height: 1.2; $content-line-height: 1.25; $body-text-color: $grey-dk-300; @@ -27,22 +27,23 @@ $feedback-color: rgba(gold, 0.1); // {% comment %} https://codepen.io/AgnusDei/pen/NWPbOxL {% endcomment %} .side-bar-background { - @include mq(md) - { position: absolute; - top:0; - left:0; - width:100%; - height:98%; }; + @include mq(md) { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 98%; + } + + ; // Put the title on top z-index: -1; // box-shadow: 2px 3px 20px black, 0 0 125px #8f5922 inset; - box-shadow: 0 0 125px #8f5922 inset; + box-shadow: 0 0 125px #8f5922 inset; background: #fffed0; - background-image: url(data:image/png;base64,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); - filter: - url(#wavy2) - drop-shadow(2px 2px 3px black); + background-image: url(data:image/png;base64,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); + filter: url(#wavy2) drop-shadow(2px 2px 3px black); } diff --git a/_sass/custom/custom.scss b/_sass/custom/custom.scss index e0565c7..77b295b 100644 --- a/_sass/custom/custom.scss +++ b/_sass/custom/custom.scss @@ -47,12 +47,42 @@ div.linkrow { } } -div.highlighter-rouge div.highlight { - background: lighten(#E5D780, 15%); - padding: 5px; - margin: 10px; +.site-nav { + padding-top: 1rem; - pre { - background: inherit; + .site-nav { + padding-top: 0.2rem; + padding-bottom: 0.2rem; + } +} + +.highlight, +pre.highlight, +.highlight pre, +.highlight .hll, +div.highlighter-rouge { + background: #f2ebc0; +} + +div.nav-collapse { + padding-top: 1rem; + width: 100%; + font-size: 0.7rem; + display: flex; + align-items: center; + justify-content: center; + padding-left: 20px; + padding-right: 10px; + + span { + margin: 0 10px; + } + + &:before, + &:after { + background: #000; + content: ""; + height: 1px; + flex: 1; } } diff --git a/api.md b/api.md new file mode 100644 index 0000000..8e2d881 --- /dev/null +++ b/api.md @@ -0,0 +1,34 @@ +--- +layout: default +# This title (API) and path (api) is hard-coded in all children (key parent: API) +# and in all grandchildren (_layouts/odoc.html in the breadcrumbs) +title: API +has_children: true +has_toc: false +nav_order: 20 +--- + +# Packages + +Codex includes the following ocaml packages. + +{% for p in site.data.packages %} +{% assign package = p[1] %} +## {{ package.name }} + +{: style="margin-bottom: 0.4rem;"} +{{ package.description }} + + +{% include shields.html package=package %} + + +{% endfor %} diff --git a/api/patricia-tree.md b/api/patricia-tree.md new file mode 100644 index 0000000..02f10be --- /dev/null +++ b/api/patricia-tree.md @@ -0,0 +1,57 @@ +--- +layout: default +parent: API +title: Patricia Tree +url: /api/patricia-tree +redirect_from: + - /patricia-tree/ + - /patricia-tree.html +--- + +# Patricia Tree API + +{% include shields.html package=site.data.packages.patricia-tree %} + +This is an [OCaml](https://ocaml.org/) library that implements sets and maps as +Patricia Trees, as described in Okasaki and Gill's 1998 paper +[*Fast mergeable integer maps*](https://www.semanticscholar.org/paper/Fast-Mergeable-Integer-Maps-Okasaki-Gill/23003be706e5f586f23dd7fa5b2a410cc91b659d). +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]("https://github.com/codex-semantics-library/patricia-tree) +under an [LGPL-2.1](https://choosealicense.com/licenses/lgpl-2.1/) license. + +{: .note } +For a quick overview of how to use the library, see the [examples](/api/patricia-tree/{{ site.data.packages.patricia-tree.latest-version }}/#examples). + +## Documentation versions + +See any of these for more details on this library, what it can do, some +small examples and the full documentation. + + +- [patricia-tree – v0.10.0](/api/patricia-tree/v0.10.0/) – latest version +- [patricia-tree – v0.9.0](/api/patricia-tree/v0.9.0/) +- [patricia-tree – main](/api/patricia-tree/main/) – development version (unreleased) + +Changes between versions are listed in the +[changelog](https://github.com/codex-semantics-library/patricia-tree/blob/main/CHANGELOG.md). + +## Installation + +This library can be installed with [opam](https://opam.ocaml.org/): +```bash +opam install patricia-tree +``` + +Alternatively, you can clone the source repository and compile with [dune](https://dune.build/): +```bash +git clone git@github.com:codex-semantics-library/patricia-tree.git +cd patricia-tree +opan install . --deps-only +dune build -p patricia-tree +dune install +# To build documentation +opam install . --deps-only --with-doc +dune build @doc +``` diff --git a/assets/css/api.css b/assets/css/api.css new file mode 100644 index 0000000..5fef35c --- /dev/null +++ b/assets/css/api.css @@ -0,0 +1,1306 @@ +.pageAPI { + padding-top: 10px; +} + +h3 { + font-size: 1.25rem !important; +} + +li.raises>p:first-of-type { + display: inline; +} + +/* override just-the-docs labels (use for labelled arguments in OCaml) */ +code .label { + color: #f7931c; + background-color: transparent; + text-transform: none; + padding: 0; + margin: 0; +} + +.pageAPI>.wrap { + position: relative; + margin: 0 auto; + padding: 0 25px 0 25px; + z-index: 2; +} + +/* Overload padding for pages with Navigation side bar */ + +.pageAPI>.wrap { + padding: 0 25px 0 55px; +} + +@media (min-width: 768px) { + .pageAPI>.wrap { + padding: 0 25px 0 260px; + } +} + +@media (min-width: 1280px) { + .pageAPI>.wrap { + padding: 0 25px 0 280px; + } +} + +/* 1260 + navigation margins (25*2) + navigation 210px*/ + +@media (min-width: 1810px) { + .pageAPI>.wrap { + max-width: 1260px; + margin: 0 auto; + padding: 0 25px; + } +} + +.navigation { + display: block; + top: 64px; + padding: 10px; + width: 100%; + min-height: 20px; + position: fixed; + background-color: white; + z-index: 40; + font-size: 20px; + font-weight: bold; +} + +@media (min-width: 768px) { + .navigation { + font-size: 20px; + top: 60px; + padding-left: 15px; + } +} + +@media (min-width: 1280px) { + .navigation { + font-size: 24px; + top: 65px; + padding-left: 40px; + } +} + +.navigation a { + color: #484848; +} + +.menu-button { + display: block; + text-align: center; + background: none; + cursor: pointer; + border-right: 2px solid #f7931c; + padding: 10px; +} + +@media (min-width: 768px) { + .menu-button { + padding: 0; + margin-bottom: -128px; + /* compensate absolute footer */ + border-radius: 0; + } +} + +.nav-check { + display: none; +} + +.api-menu { + display: block; + overflow-y: auto; + overflow-x: visible; + height: 100%; + width: 0; + margin-top: 20px; + padding-bottom: 148px; + /* compensate absolute footer */ +} + +@media (min-width: 768px) { + .api-menu { + padding: 45px 15px 148px 15px; + width: 100%; + min-width: 190px; + } +} + +@media (min-width: 1280px) { + .api-menu { + min-width: 210px; + padding-left: 40px; + } +} + +.nav-check:checked~.api-menu { + padding: 30px 15px 0 25px; + width: 100%; + min-width: 210px; +} + +.api-menu li, +.api-menu ul { + text-align: left; + margin-left: 0; + padding-left: 0; +} + +.api-menu ul { + margin-top: 10px; +} + +.api-menu li { + list-style-type: none; +} + +@media (min-width: 768px) { + .api-menu { + font-size: 18px; + } +} + +@media (min-width: 1280px) { + .api-menu { + font-size: 20px; + } +} + +.api-menu a { + color: #484848; +} + +.api-menu .selected { + color: #f7931c; +} + +.check-zone { + height: 100vh; +} + +.sideMenu { + position: fixed; + height: 100vh; + display: inline-flex; + padding-top: 65px; + background: white; + z-index: 20; +} + +.sideMenu label:after { + content: "COMPONENTS"; + font-weight: bolder; + display: inline-block; + position: relative; + font-size: 1.1em; + writing-mode: vertical-rl; + text-orientation: sideways; + padding-top: 60px; + width: 20px; + color: #f16521; +} + +.nav-check-deactivator { + display: none; +} + +@media (min-width: 768px) { + .sideMenu { + z-index: 10; + } + + .sideMenu label:after { + display: none; + } + + .nav-check-deactivator { + display: block; + position: fixed; + background: transparent; + height: 100vh; + width: 6px; + z-index: 4; + left: 230px; + } +} + +@media (min-width: 1280px) { + .nav-check-deactivator { + left: 250px; + } +} + +/* START OF ODOC */ + + +/* Copyright (c) 2016 The odoc contributors. All rights reserved. + Distributed under the ISC license, see terms at the end of the file. + %%NAME%% %%VERSION%% */ + +:root { + --main-background: #FFFFFF; + + --color: #484848; + --source-color: grey; + --anchor-hover: #6d071a; + --anchor-color: #d5d5d5; + --xref-shadow: #cc6666; + --xref-unresolved: #cc6666; + --header-shadow: #ddd; + --by-name-version-color: #aaa; + --by-name-nav-link-color: #222; + --target-background: #fdeee6; + --target-shadow: #ffdec3; + --pre-border-color: #eee; + --code-background: #f2ebc0; + --link-color: #5f2832; + + --toc-color: #1F2D3D; + --toc-before-color: #777; + --toc-background: #f6f8fa; + --toc-list-border: #ccc; + + --spec-summary-border-color: #c60d2f; + --spec-summary-background: var(--code-background); + --spec-summary-hover-background: #ebeff2; + --spec-details-after-background: rgba(0, 4, 15, 0.05); + --spec-details-after-shadow: rgba(204, 204, 204, 0.53); +} + +/* Reset a few things. */ + +html { + scroll-padding-top: 120px; +} + +body.odoc-src { + margin-right: calc(10vw + 20ex); +} + +/* Text alignements, this should be forbidden. */ + +.left { + text-align: left; +} + +.right { + text-align: right; +} + +.center { + text-align: center; +} + +/* Links and anchors */ + +a { + text-decoration: none; +} + +code a, +pre a, +tt a { + color: var(--link-color); +} + +/* Linked highlight */ +*:target { + background-color: var(--target-background) !important; + box-shadow: 0 0px 0 1px var(--target-shadow) !important; + border-radius: 1px; +} + +*:hover>a.anchor { + visibility: visible; +} + +a.anchor:before { + content: "#"; +} + +a.anchor:hover { + box-shadow: none; + text-decoration: none; + color: var(--anchor-hover); +} + +.anchor { + visibility: hidden; + margin-left: -1em; + font-weight: normal; + font-style: normal; + padding-right: 0.1em; + padding-left: 0.4em; + padding-top: 0px; + margin-top: 0px; + /* To remain selectable */ + color: var(--anchor-color); +} + +.spec>a.anchor { + margin-left: -2.3em; + padding-right: 0.9em; +} + +.xref-unresolved { + color: var(--xref-unresolved); +} + +.xref-unresolved:hover { + box-shadow: 0 1px 0 0 var(--xref-shadow); +} + +/* Source links float inside preformated text or headings. */ +a.source_link { + float: right; + color: var(--source-color); + font-size: initial; +} + +/* Disable anchor headings generated by jekyll-anchor-headings (odoc already has one) */ +a.anchor-heading { + display: none; +} + +/* Comment delimiters, hidden but accessible to screen readers and + selected for copy/pasting */ + +/* Taken from bootstrap */ +/* See also https://stackoverflow.com/a/27769435/4220738 */ +.comment-delim { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +/* Preformatted and code */ + +tt, +code, +pre { + font-family: monospace; + font-weight: 400; +} + +pre { + padding: 0.1em; + border: 1px solid var(--pre-border-color); + border-radius: 5px; + overflow-x: auto; +} + +p code, +li code { + border-radius: 3px; + padding: 0 0.3ex; + color: #458; +} + +:not(pre, figure) code { + background-color: transparent; +} + +a code { + color: var(--link-color); +} + +code { + white-space: pre-wrap; +} + +/* Code blocks (e.g. Examples) */ + +pre code { + font-size: 0.893rem; +} + +/* Code lexemes */ + +.keyword { + font-weight: 500; + color: #309100; +} + +.arrow { + white-space: nowrap +} + +/* Module member specification */ + +.spec { + background-color: var(--spec-summary-background); + border-radius: 3px; + border-left: 4px solid var(--spec-summary-border-color); + border-right: 5px solid transparent; + padding: 0.35em 0.7em; +} + +li:not(:last-child)>.def-doc { + margin-bottom: 15px; +} + +/* Spacing between items */ +div.odoc-spec, +.odoc-include { + margin-bottom: 2em; +} + +.spec.type .variant p, +.spec.type .record p { + margin: 5px; +} + +.spec.type .variant, +.spec.type .record { + margin-left: 2ch; + list-style: none; + /* display: flex; + flex-wrap: wrap; + row-gap: 4px; */ +} + +.spec.type .record>code, +.spec.type .variant>code { + min-width: 40%; +} + +.spec.type>ol { + margin-top: 0; + margin-bottom: 0; +} + +.spec.type .record>.def-doc, +.spec.type .variant>.def-doc { + min-width: 50%; + padding: 0.25em 0.5em; + margin-left: 10%; + border-radius: 3px; + flex-grow: 1; + background: var(--main-background); + box-shadow: 2px 2px 4px lightgrey; +} + +div.def { + margin-top: 0; + text-indent: -2ex; + padding-left: 2ex; +} + +div.def-doc>*:first-child { + margin-top: 0; +} + +/* Records and variants FIXME */ + +div.def table { + text-indent: 0em; + padding: 0; + margin-left: -2ex; +} + +td.def { + padding-left: 2ex; +} + +td.def-doc *:first-child { + margin-top: 0em; +} + +/* Lists of @tags */ + +.at-tags { + list-style-type: none; + margin-left: -3ex; +} + +.at-tags li { + padding-left: 3ex; + text-indent: -3ex; +} + +.at-tags .at-tag { + text-transform: capitalize +} + +/* Alert emoji */ + +.alert::before, +.deprecated::before { + content: '⚠️ '; +} + +/* Lists of modules */ + +.modules { + list-style-type: none; + margin-left: -3ex; +} + +.modules li { + padding-left: 3ex; + text-indent: -3ex; + margin-top: 5px +} + +.modules .synopsis { + padding-left: 1ch; +} + +/* Odig package index */ + +.packages { + list-style-type: none; + margin-left: -3ex; +} + +.packages li { + padding-left: 3ex; + text-indent: -3ex +} + +.packages li a.anchor { + padding-right: 0.5ch; + padding-left: 3ch; +} + +.packages .version { + font-size: 10px; + color: var(--by-name-version-color); +} + +.packages .synopsis { + padding-left: 1ch +} + +.by-name nav a { + text-transform: uppercase; + font-size: 18px; + margin-right: 1ex; + color: var(--by-name-nav-link-color, ); + display: inline-block; +} + +.by-tag nav a { + margin-right: 1ex; + color: var(--by-name-nav-link-color); + display: inline-block; +} + +.by-tag ol { + list-style-type: none; +} + +.by-tag ol.tags li { + margin-left: 1ch; + display: inline-block +} + +.by-tag td:first-child { + text-transform: uppercase; +} + +/* Odig package page */ + +.package nav { + display: inline; + font-size: 14px; + font-weight: normal; +} + +.package .version { + font-size: 14px; +} + +.package.info { + margin: 0; +} + +.package.info td:first-child { + font-style: italic; + padding-right: 2ex; +} + +.package.info ul { + list-style-type: none; + display: inline; + margin: 0; +} + +.package.info li { + display: inline-block; + margin: 0; + margin-right: 1ex; +} + +#info-authors li, +#info-maintainers li { + display: block; +} + +/* Sidebar and TOC */ + +.odoc-toc:before { + display: block; + content: "Contents"; + text-transform: uppercase; + font-size: 1em; + margin: 1.414em 0 0.5em; + font-weight: 500; + color: var(--toc-before-color); + line-height: 1.2; +} + +.odoc-toc { + position: fixed; + top: 0px; + bottom: 0px; + left: 0px; + max-width: 30ex; + min-width: 26ex; + width: 20%; + background: var(--toc-background); + overflow: auto; + color: var(--toc-color); + padding-left: 2ex; + padding-right: 2ex; +} + +.odoc-toc ul li a { + font-size: 0.95em; + color: var(--color); + font-weight: 400; + line-height: 1.6em; + display: block; +} + +.odoc-toc ul li a:hover { + box-shadow: none; +} + +/* First level titles */ + +.odoc-toc>ul>li>a { + font-weight: 500; +} + +.odoc-toc li ul { + margin: 0px; +} + +.odoc-toc ul { + list-style-type: none; +} + +.odoc-toc ul li { + margin: 0; +} + +.odoc-toc>ul>li { + margin-bottom: 0.3em; +} + +.odoc-toc ul li li { + border-left: 1px solid var(--toc-list-border); + margin-left: 5px; + padding-left: 12px; +} + +/* Tables */ + +.odoc-table { + margin: 1em; +} + +.odoc-table td, +.odoc-table th { + padding-left: 0.5em; + padding-right: 0.5em; + border: 1px solid black; +} + +.odoc-table th { + font-weight: bold; +} + +/* Mobile adjustements. */ + +@media only screen and (max-width: 110ex) { + .odoc-toc { + position: static; + width: auto; + min-width: unset; + max-width: unset; + border: none; + padding: 0.2em 1em; + border-radius: 5px; + margin-bottom: 2em; + } +} + +/* Print adjustements. */ + +@media print { + body { + color: black; + background: white; + } + + body nav:first-child { + visibility: hidden; + } +} + +/* Source code. */ + +.source_container { + display: flex; +} + +.source_line_column { + padding-right: 0.5em; + text-align: right; + background: #eee8d5; +} + +.source_line { + padding: 0 1em; +} + +.source_code { + flex-grow: 1; + background: #fdf6e3; + padding: 0 0.3em; + color: #657b83; +} + +/* Source directories */ + +.odoc-directory::before { + content: "📁"; + margin: 0.3em; + font-size: 1.3em; +} + +.odoc-file::before { + content: "📄"; + margin: 0.3em; + font-size: 1.3em; +} + +.odoc-folder-list { + list-style: none; +} + +/* Details */ + +details { + border: 1px solid #f7931c; + border-radius: 5px; + padding: 1em 1em; + margin-bottom: 1em; +} + +details:hover { + color: #242424 !important; + background-color: #f9f9f9 !important; +} + +details summary:focus, +details:hover summary { + color: #f16521; +} + +details.empty:hover, +details.empty summary, +details.empty summary:hover { + color: #484848 !important; + background-color: transparent !important; +} + +details summary { + cursor: pointer; + padding: 10px 20px 10px 35px !important; + margin-bottom: 20px; +} + +details.empty summary { + cursor: auto; +} + +details summary::before { + list-style: inside; + margin-top: 5px; + margin-left: 30px; + font-size: 100%; +} + +details[open] summary::before { + margin-top: 12px; + margin-left: 25px; + font-size: 65%; +} + +details[open].empty summary::before, +details.empty summary::before { + display: none; +} + +.hljs { + display: block; + background: var(--code-background); + padding: 0.5em; + color: var(--color); + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag { + color: #309100; +} + +.hljs-type, +.hljs-class .hljs-title { + color: #458; + font-weight: 500; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.type-var, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + + +.VAL, +.TYPE, +.LET, +.REC, +.IN, +.OPEN, +.NONREC, +.MODULE, +.METHOD, +.LETOP, +.INHERIT, +.INCLUDE, +.FUNCTOR, +.EXTERNAL, +.CONSTRAINT, +.ASSERT, +.AND, +.END, +.CLASS, +.STRUCT, +.SIG { + color: #859900; + ; +} + +.WITH, +.WHILE, +.WHEN, +.VIRTUAL, +.TRY, +.TO, +.THEN, +.PRIVATE, +.OF, +.NEW, +.MUTABLE, +.MATCH, +.LAZY, +.IF, +.FUNCTION, +.FUN, +.FOR, +.EXCEPTION, +.ELSE, +.TO, +.DOWNTO, +.DO, +.DONE, +.BEGIN, +.AS { + color: #cb4b16; +} + +.TRUE, +.FALSE { + color: #b58900; +} + +.failwith, +.INT, +.SEMISEMI, +.LIDENT { + color: #2aa198; +} + +.STRING, +.CHAR, +.UIDENT { + color: #b58900; +} + +.DOCSTRING { + color: #268bd2; +} + +.COMMENT { + color: #93a1a1; +} + +span .constructor { + color: #567bc3; +} + +:root { + --search-bar-height: 25px; + --search-padding-top: 1rem; + --search-results-border: #505050; + --search-results-shadow: #404040; + --search-snake: #82aaff; + --search-hover: var(--code-background); + --li-code-background: #f6f8fa; + --li-code-color: #6d071a; +} + +.odoc-search { + position: sticky; + top: 0; + background: var(--main-background); + /* This amounts to fit-content when the search is not active, but when you + have the search results displayed, you do not want the height of the search + container to change. */ + height: calc(var(--search-bar-height) + var(--search-padding-top)); + width: 100%; + padding-top: var(--search-padding-top); + z-index: 1; + grid-row: 1; + grid-column-start: 1; + grid-column-end: 3; +} + + +.odoc-search .search-inner { + width: 100%; + position: relative; + left: 0; + display: grid; + /* The second column is for the search snake, which has 0 width */ + grid-template-columns: 1fr 0fr; + grid-row-gap: 1rem; + /* The second row is for the search results. It has a width, but only */ + grid-template-rows: min-content 0px; + background: transparent; +} + +.odoc-search .search-bar { + position: relative; + z-index: 2; + font-size: 1em; + transition: font-size 0.3s; + box-shadow: 0px 0px 0.2rem 0.3em var(--main-background); + height: var(--search-bar-height); +} + +.odoc-search:focus-within .search-bar { + font-size: 1.1em; +} + +.odoc-search:not(:focus-within) .search-result { + display: none; +} + +.odoc-search .search-result:empty { + display: none; +} + +.odoc-search .search-result { + grid-row: 2; + background: var(--toc-background); + position: absolute; + left: 0; + right: 0; + border: solid; + border-color: var(--search-results-border); + border-width: 1px; + border-radius: 6px; + box-shadow: 0 3px 10px 2px var(--search-results-shadow), 0 0 3px 4px var(--main-background), 0px -1rem 0px 0px var(--main-background); + /* Works better on smallish screens with this */ + max-height: calc(min(40rem, 50vh)); + overflow-y: auto; + padding: 0; +} + +.search-bar { + /* inputs are of fixed size by default, even if you display:block them */ + width: 100%; +} + +.odoc-search .search-no-result { + color: var(--color); + border-bottom: var(--search-results-border) solid 0px; + background-color: inherit; + outline: 0; + padding: 10px; + padding-right: 0.5rem; +} + +.search-bar-container { + display: flex; + align-items: stretch; + border-bottom: 1rem solid var(--main-background); +} + +.search-snake { + grid-row: 1; + grid-column: 2; + display: flex; + align-items: center; + width: 0; + z-index: 2; + position: relative; + left: 0; + margin-top: 4px; + margin-bottom: 4px; + /* Otherwise the search snake flickers for very fast searches. */ + transition: opacity 0.2s; + opacity: 0; +} + +.search-snake.search-busy { + opacity: 1; +} + +.search-snake:before { + content: " "; + display: block; + aspect-ratio: 1 / 1; + height: 100%; + margin-right: 4px; + border-radius: 50%; + border: 3px solid #aaa; + border-color: var(--search-snake) transparent var(--search-snake) transparent; + animation: search-snake 1.2s linear infinite; + position: absolute; + right: 0; +} + +@keyframes search-snake { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +:root { + --kind-font-size-factor: 0.8; +} + +.odoc-search .search-entry { + color: var(--color); + display: grid; + /* Possible kinds are the following : + "doc" "type" "mod" "exn" "class" "meth" "cons" "sig" "cons" "field" "val" + and "ext". + As the longest is 5 characters (and the font monospace), we give 5 + character size to the column. However the font used for kind is a little + smaller, so we adjust by this factor. + */ + grid-template-columns: [kinds] calc(var(--kind-font-size-factor) * 5ch) [titles] 1fr; + column-gap: 0.5rem; + border-bottom: var(--search-results-border) solid 1px; + background-color: inherit; + outline: 0; + padding: 0.2rem 0.4rem 0.2rem 0.7rem; +} + +.odoc-search .search-entry p { + margin: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.odoc-search .search-entry:focus-visible { + box-shadow: none; + background-color: var(--target-background); +} + +.odoc-search .search-entry:hover { + box-shadow: none; + background-color: var(--search-hover); +} + +.odoc-search .search-entry .entry-kind { + grid-row: 1/2; + grid-column: 1/2; + line-height: 1.4rem; + font-size: calc(var(--kind-font-size-factor) * 0.8em); + font-weight: bold; + text-align: right; + position: relative; + bottom: 0; +} + +.odoc-search .search-entry pre { + border: none; + margin: 0; +} + +.odoc-search .search-entry pre code { + font-size: 1em; + background-color: var(--li-code-background); + color: var(--li-code-color); + border-radius: 3px; + padding: 0 0.3ex; +} + +.odoc-search .search-entry .entry-title { + width: 100%; + display: block; + grid-column: 2/2; + grid-row: 1/2; + align-self: end; + line-height: 1.4rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.odoc-search .entry-name { + font-weight: bold; +} + +.odoc-search .prefix-name { + font-weight: bold; +} + +.odoc-search .search-entry .prefix-name { + opacity: 0.7; +} + +.odoc-search .entry-rhs { + white-space: nowrap; +} + +.odoc-search .search-entry .entry-content { + flex-grow: 1; + flex-shrink: 1; + min-width: 0; +} + +.odoc-search .search-entry .entry-comment { + max-height: 1.5em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 0.95em; + grid-row: 2/2; + grid-column: 2/2; +} + +.odoc-search .search-entry .entry-comment ul { + white-space: nowrap; + display: inline; +} + +.odoc-search .search-entry .entry-comment li { + display: inline; + white-space: nowrap; +} + +.odoc-search .search-entry .entry-comment ul>li::before { + content: '•'; +} + +.odoc-search .search-entry .entry-comment div { + display: inline; + white-space: nowrap; +} + +.odoc-search .search-entry .entry-comment p { + display: inline; + white-space: nowrap; +} + +.odoc-search .search-entry .entry-comment code { + display: inline; + white-space: nowrap; +} + + +/*--------------------------------------------------------------------------- + Copyright (c) 2016 The odoc contributors + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ---------------------------------------------------------------------------*/ diff --git a/assets/css/pygments.css b/assets/css/pygments.css new file mode 100644 index 0000000..0feb7fb --- /dev/null +++ b/assets/css/pygments.css @@ -0,0 +1,72 @@ +/* ============================================================================== + Pygments (pandoc built-in style) + ============================================================================== + Style based on Pygments' default colors. + + This stylesheet was produced using Pandoc v2.7.2. + + Pandoc is (c) 2006-2017 John MacFarlane (jgm@berkeley.edu). + Released under the GPL, version 2 or greater. + ------------------------------------------------------------------------------ +*/ +a.sourceLine { display: inline-block; line-height: 1.25; } +a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; } +a.sourceLine:empty { height: 1.2em; } +.sourceCode { overflow: visible; } +code.sourceCode { white-space: pre; position: relative; } +div.sourceCode { margin: 1em 0; } +pre.sourceCode { margin: 0; } +@media screen { +div.sourceCode { overflow: auto; } +} +@media print { +code.sourceCode { white-space: pre-wrap; } +a.sourceLine { text-indent: -1em; padding-left: 1em; } +} +pre.numberSource a.sourceLine + { position: relative; left: -4em; } +pre.numberSource a.sourceLine::before + { content: attr(title); + position: relative; left: -1em; text-align: right; vertical-align: baseline; + border: none; pointer-events: all; display: inline-block; + -webkit-touch-callout: none; -webkit-user-select: none; + -khtml-user-select: none; -moz-user-select: none; + -ms-user-select: none; user-select: none; + padding: 0 4px; width: 4em; + color: #aaaaaa; + } +pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; } +div.sourceCode + { } +@media screen { +a.sourceLine::before { text-decoration: underline; } +} +code span.al { color: #ff0000; font-weight: bold; } /* Alert */ +code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */ +code span.at { color: #7d9029; } /* Attribute */ +code span.bn { color: #40a070; } /* BaseN */ +code span.bu { } /* BuiltIn */ +code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */ +code span.ch { color: #4070a0; } /* Char */ +code span.cn { color: #880000; } /* Constant */ +code span.co { color: #60a0b0; font-style: italic; } /* Comment */ +code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */ +code span.do { color: #ba2121; font-style: italic; } /* Documentation */ +code span.dt { color: #902000; } /* DataType */ +code span.dv { color: #40a070; } /* DecVal */ +code span.er { color: #ff0000; font-weight: bold; } /* Error */ +code span.ex { } /* Extension */ +code span.fl { color: #40a070; } /* Float */ +code span.fu { color: #06287e; } /* Function */ +code span.im { } /* Import */ +code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */ +code span.kw { color: #007020; font-weight: bold; } /* Keyword */ +code span.op { color: #666666; } /* Operator */ +code span.ot { color: #007020; } /* Other */ +code span.pp { color: #bc7a00; } /* Preprocessor */ +code span.sc { color: #4070a0; } /* SpecialChar */ +code span.ss { color: #bb6688; } /* SpecialString */ +code span.st { color: #4070a0; } /* String */ +code span.va { color: #19177c; } /* Variable */ +code span.vs { color: #4070a0; } /* VerbatimString */ +code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ diff --git a/assets/js/highlight.pack.js b/assets/js/highlight.pack.js new file mode 100644 index 0000000..7d1bcd0 --- /dev/null +++ b/assets/js/highlight.pack.js @@ -0,0 +1,634 @@ +/*! + Highlight.js v11.7.0 (git: 82688fad18) + (c) 2006-2022 undefined and other contributors + License: BSD-3-Clause + */ +var hljs=function(){"use strict";var e={exports:{}};function t(e){ +return e instanceof Map?e.clear=e.delete=e.set=()=>{ +throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var i=e[n] +;"object"!=typeof i||Object.isFrozen(i)||t(i)})),e} +e.exports=t,e.exports.default=t;class n{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function i(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function r(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n} +const s=e=>!!e.scope||e.sublanguage&&e.language;class o{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=i(e)}openNode(e){if(!s(e))return;let t="" +;t=e.sublanguage?"language-"+e.language:((e,{prefix:t})=>{if(e.includes(".")){ +const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(e.scope,{prefix:this.classPrefix}),this.span(t)} +closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}const a=(e={})=>{const t={children:[]} +;return Object.assign(t,e),t};class c{constructor(){ +this.rootNode=a(),this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t=a({scope:e}) +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +c._collapse(e)})))}}class l extends c{constructor(e){super(),this.options=e} +addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())} +addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root +;n.sublanguage=!0,n.language=t,this.add(n)}toHTML(){ +return new o(this,this.options).value()}finalize(){return!0}}function g(e){ +return e?"string"==typeof e?e:e.source:null}function d(e){return p("(?=",e,")")} +function u(e){return p("(?:",e,")*")}function h(e){return p("(?:",e,")?")} +function p(...e){return e.map((e=>g(e))).join("")}function f(...e){const t=(e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e);return"("+(t.capture?"":"?:")+e.map((e=>g(e))).join("|")+")"} +function b(e){return RegExp(e.toString()+"|").exec("").length-1} +const m=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function E(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=g(e),r="";for(;i.length>0;){const e=m.exec(i);if(!e){r+=i;break} +r+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+t):(r+=e[0], +"("===e[0]&&n++)}return r})).map((e=>`(${e})`)).join(t)} +const x="[a-zA-Z]\\w*",w="[a-zA-Z_]\\w*",y="\\b\\d+(\\.\\d+)?",_="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",O="\\b(0b[01]+)",v={ +begin:"\\\\[\\s\\S]",relevance:0},N={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[v]},k={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[v]},M=(e,t,n={})=>{const i=r({scope:"comment",begin:e,end:t, +contains:[]},n);i.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const s=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return i.contains.push({begin:p(/[ ]+/,"(",s,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),i +},S=M("//","$"),R=M("/\\*","\\*/"),j=M("#","$");var A=Object.freeze({ +__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:x,UNDERSCORE_IDENT_RE:w, +NUMBER_RE:y,C_NUMBER_RE:_,BINARY_NUMBER_RE:O, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=p(t,/.*\b/,e.binary,/\b.*/)),r({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +BACKSLASH_ESCAPE:v,APOS_STRING_MODE:N,QUOTE_STRING_MODE:k,PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},COMMENT:M,C_LINE_COMMENT_MODE:S,C_BLOCK_COMMENT_MODE:R,HASH_COMMENT_MODE:j, +NUMBER_MODE:{scope:"number",begin:y,relevance:0},C_NUMBER_MODE:{scope:"number", +begin:_,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:O,relevance:0}, +REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//, +end:/\/[gimuy]*/,illegal:/\n/,contains:[v,{begin:/\[/,end:/\]/,relevance:0, +contains:[v]}]}]},TITLE_MODE:{scope:"title",begin:x,relevance:0}, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:w,relevance:0},METHOD_GUARD:{ +begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function I(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function T(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function L(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=I,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function B(e,t){ +Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function D(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function H(e,t){ +void 0===e.relevance&&(e.relevance=1)}const P=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords,e.begin=p(n.beforeMatch,d(n.begin)),e.starts={ +relevance:0,contains:[Object.assign(n,{endsParent:!0})] +},e.relevance=0,delete n.beforeMatch +},C=["of","and","for","in","not","or","if","then","parent","list","value"] +;function $(e,t,n="keyword"){const i=Object.create(null) +;return"string"==typeof e?r(n,e.split(" ")):Array.isArray(e)?r(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,$(e[n],t,n))})),i;function r(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){ +return t?Number(t):(e=>C.includes(e.toLowerCase()))(e)?0:1}const z={},K=e=>{ +console.error(e)},W=(e,...t)=>{console.log("WARN: "+e,...t)},X=(e,t)=>{ +z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0) +},G=Error();function Z(e,t,{key:n}){let i=0;const r=e[n],s={},o={} +;for(let e=1;e<=t.length;e++)o[e+i]=r[e],s[e+i]=!0,i+=b(t[e-1]) +;e[n]=o,e[n]._emit=s,e[n]._multi=!0}function F(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw K("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +G +;if("object"!=typeof e.beginScope||null===e.beginScope)throw K("beginScope must be object"), +G;Z(e,e.begin,{key:"beginScope"}),e.begin=E(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw K("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +G +;if("object"!=typeof e.endScope||null===e.endScope)throw K("endScope must be object"), +G;Z(e,e.end,{key:"endScope"}),e.end=E(e.end,{joinWith:""})}})(e)}function V(e){ +function t(t,n){ +return RegExp(g(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) +}class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=b(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(E(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class i{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=r(e.classNameAliases||{}),function n(s,o){const a=s +;if(s.isCompiled)return a +;[T,D,F,P].forEach((e=>e(s,o))),e.compilerExtensions.forEach((e=>e(s,o))), +s.__beforeBegin=null,[L,B,H].forEach((e=>e(s,o))),s.isCompiled=!0;let c=null +;return"object"==typeof s.keywords&&s.keywords.$pattern&&(s.keywords=Object.assign({},s.keywords), +c=s.keywords.$pattern, +delete s.keywords.$pattern),c=c||/\w+/,s.keywords&&(s.keywords=$(s.keywords,e.case_insensitive)), +a.keywordPatternRe=t(c,!0), +o&&(s.begin||(s.begin=/\B|\b/),a.beginRe=t(a.begin),s.end||s.endsWithParent||(s.end=/\B|\b/), +s.end&&(a.endRe=t(a.end)), +a.terminatorEnd=g(a.end)||"",s.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(s.end?"|":"")+o.terminatorEnd)), +s.illegal&&(a.illegalRe=t(s.illegal)), +s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>r(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?r(e,{ +starts:e.starts?r(e.starts):null +}):Object.isFrozen(e)?r(e):e))("self"===e?s:e)))),s.contains.forEach((e=>{n(e,a) +})),s.starts&&n(s.starts,o),a.matcher=(e=>{const t=new i +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){ +return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{ +constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} +const Y=i,Q=r,ee=Symbol("nomatch");var te=(t=>{ +const i=Object.create(null),r=Object.create(null),s=[];let o=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",c={ +disableAutodetect:!0,name:"Plain text",contains:[]};let g={ +ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:l};function b(e){ +return g.noHighlightRe.test(e)}function m(e,t,n){let i="",r="" +;"object"==typeof t?(i=e, +n=t.ignoreIllegals,r=t.language):(X("10.7.0","highlight(lang, code, ...args) has been deprecated."), +X("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +r=e,i=t),void 0===n&&(n=!0);const s={code:i,language:r};k("before:highlight",s) +;const o=s.result?s.result:E(s.language,s.code,n) +;return o.code=s.code,k("after:highlight",o),o}function E(e,t,r,s){ +const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(S) +;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(S),n="" +;for(;t;){n+=S.substring(e,t.index) +;const r=y.case_insensitive?t[0].toLowerCase():t[0],s=(i=r,N.keywords[i]);if(s){ +const[e,i]=s +;if(M.addText(n),n="",c[r]=(c[r]||0)+1,c[r]<=7&&(R+=i),e.startsWith("_"))n+=t[0];else{ +const n=y.classNameAliases[e]||e;M.addKeyword(t[0],n)}}else n+=t[0] +;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(S)}var i +;n+=S.substring(e),M.addText(n)}function d(){null!=N.subLanguage?(()=>{ +if(""===S)return;let e=null;if("string"==typeof N.subLanguage){ +if(!i[N.subLanguage])return void M.addText(S) +;e=E(N.subLanguage,S,!0,k[N.subLanguage]),k[N.subLanguage]=e._top +}else e=x(S,N.subLanguage.length?N.subLanguage:null) +;N.relevance>0&&(R+=e.relevance),M.addSublanguage(e._emitter,e.language) +})():l(),S=""}function u(e,t){let n=1;const i=t.length-1;for(;n<=i;){ +if(!e._emit[n]){n++;continue}const i=y.classNameAliases[e[n]]||e[n],r=t[n] +;i?M.addKeyword(r,i):(S=r,l(),S=""),n++}}function h(e,t){ +return e.scope&&"string"==typeof e.scope&&M.openNode(y.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(M.addKeyword(S,y.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +S=""):e.beginScope._multi&&(u(e.beginScope,t),S="")),N=Object.create(e,{parent:{ +value:N}}),N}function p(e,t,i){let r=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,i);if(r){if(e["on:end"]){const i=new n(e) +;e["on:end"](t,i),i.isMatchIgnored&&(r=!1)}if(r){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return p(e.parent,t,i)}function f(e){ +return 0===N.matcher.regexIndex?(S+=e[0],1):(I=!0,0)}function b(e){ +const n=e[0],i=t.substring(e.index),r=p(N,e,i);if(!r)return ee;const s=N +;N.endScope&&N.endScope._wrap?(d(), +M.addKeyword(n,N.endScope._wrap)):N.endScope&&N.endScope._multi?(d(), +u(N.endScope,e)):s.skip?S+=n:(s.returnEnd||s.excludeEnd||(S+=n), +d(),s.excludeEnd&&(S=n));do{ +N.scope&&M.closeNode(),N.skip||N.subLanguage||(R+=N.relevance),N=N.parent +}while(N!==r.parent);return r.starts&&h(r.starts,e),s.returnEnd?0:n.length} +let m={};function w(i,s){const a=s&&s[0];if(S+=i,null==a)return d(),0 +;if("begin"===m.type&&"end"===s.type&&m.index===s.index&&""===a){ +if(S+=t.slice(s.index,s.index+1),!o){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=m.rule,t}return 1} +if(m=s,"begin"===s.type)return(e=>{ +const t=e[0],i=e.rule,r=new n(i),s=[i.__beforeBegin,i["on:begin"]] +;for(const n of s)if(n&&(n(e,r),r.isMatchIgnored))return f(t) +;return i.skip?S+=t:(i.excludeBegin&&(S+=t), +d(),i.returnBegin||i.excludeBegin||(S=t)),h(i,e),i.returnBegin?0:t.length})(s) +;if("illegal"===s.type&&!r){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') +;throw e.mode=N,e}if("end"===s.type){const e=b(s);if(e!==ee)return e} +if("illegal"===s.type&&""===a)return 1 +;if(A>1e5&&A>3*s.index)throw Error("potential infinite loop, way more iterations than matches") +;return S+=a,a.length}const y=O(e) +;if(!y)throw K(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const _=V(y);let v="",N=s||_;const k={},M=new g.__emitter(g);(()=>{const e=[] +;for(let t=N;t!==y;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>M.openNode(e)))})();let S="",R=0,j=0,A=0,I=!1;try{ +for(N.matcher.considerAll();;){ +A++,I?I=!1:N.matcher.considerAll(),N.matcher.lastIndex=j +;const e=N.matcher.exec(t);if(!e)break;const n=w(t.substring(j,e.index),e) +;j=e.index+n} +return w(t.substring(j)),M.closeAllNodes(),M.finalize(),v=M.toHTML(),{ +language:e,value:v,relevance:R,illegal:!1,_emitter:M,_top:N}}catch(n){ +if(n.message&&n.message.includes("Illegal"))return{language:e,value:Y(t), +illegal:!0,relevance:0,_illegalBy:{message:n.message,index:j, +context:t.slice(j-100,j+100),mode:n.mode,resultSoFar:v},_emitter:M};if(o)return{ +language:e,value:Y(t),illegal:!1,relevance:0,errorRaised:n,_emitter:M,_top:N} +;throw n}}function x(e,t){t=t||g.languages||Object.keys(i);const n=(e=>{ +const t={value:Y(e),illegal:!1,relevance:0,_top:c,_emitter:new g.__emitter(g)} +;return t._emitter.addText(e),t})(e),r=t.filter(O).filter(N).map((t=>E(t,e,!1))) +;r.unshift(n);const s=r.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 +;if(O(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=s,l=o +;return l.secondBest=a,l}function w(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=g.languageDetectRe.exec(t);if(n){const t=O(n[1]) +;return t||(W(a.replace("{}",n[1])), +W("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return +;if(k("before:highlightElement",{el:e,language:n +}),e.children.length>0&&(g.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), +console.warn("The element with unescaped HTML:"), +console.warn(e)),g.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML) +;t=e;const i=t.textContent,s=n?m(i,{language:n,ignoreIllegals:!0}):x(i) +;e.innerHTML=s.value,((e,t,n)=>{const i=t&&r[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,s.language),e.result={language:s.language,re:s.relevance, +relevance:s.relevance},s.secondBest&&(e.secondBest={ +language:s.secondBest.language,relevance:s.secondBest.relevance +}),k("after:highlightElement",{el:e,result:s,text:i})}let y=!1;function _(){ +"loading"!==document.readyState?document.querySelectorAll(g.cssSelector).forEach(w):y=!0 +}function O(e){return e=(e||"").toLowerCase(),i[e]||i[r[e]]} +function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +r[e.toLowerCase()]=t}))}function N(e){const t=O(e) +;return t&&!t.disableAutodetect}function k(e,t){const n=e;s.forEach((e=>{ +e[n]&&e[n](t)}))} +"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ +y&&_()}),!1),Object.assign(t,{highlight:m,highlightAuto:x,highlightAll:_, +highlightElement:w, +highlightBlock:e=>(X("10.7.0","highlightBlock will be removed entirely in v12.0"), +X("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{g=Q(g,e)}, +initHighlighting:()=>{ +_(),X("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +_(),X("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(e,n)=>{let r=null;try{r=n(t)}catch(t){ +if(K("Language definition for '{}' could not be registered.".replace("{}",e)), +!o)throw t;K(t),r=c} +r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&v(r.aliases,{ +languageName:e})},unregisterLanguage:e=>{delete i[e] +;for(const t of Object.keys(r))r[t]===e&&delete r[t]}, +listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v, +autoDetection:N,inherit:Q,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)} +}),t.debugMode=()=>{o=!1},t.safeMode=()=>{o=!0 +},t.versionString="11.7.0",t.regex={concat:p,lookahead:d,either:f,optional:h, +anyNumberOfTimes:u};for(const t in A)"object"==typeof A[t]&&e.exports(A[t]) +;return Object.assign(t,A),t})({});return te}() +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `reasonml` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const n="~?[a-z$_][0-9a-zA-Z$_]*",a="`?[A-Z$_][0-9a-zA-Z$_]*",s="("+["||","++","**","+.","*","/","*.","/.","..."].map((e=>e.split("").map((e=>"\\"+e)).join(""))).join("|")+"|\\|>|&&|==|===)",i="\\s+"+s+"\\s+",r={ +keyword:"and as asr assert begin class constraint do done downto else end exception external for fun function functor if in include inherit initializer land lazy let lor lsl lsr lxor match method mod module mutable new nonrec object of open or private rec sig struct then to try type val virtual when while with", +built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 ref string unit ", +literal:"true false" +},l="\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",t={ +className:"number",relevance:0,variants:[{begin:l},{begin:"\\(-"+l+"\\)"}]},c={ +className:"operator",relevance:0,begin:s},o=[{className:"identifier", +relevance:0,begin:n},c,t],g=[e.QUOTE_STRING_MODE,c,{className:"module", +begin:"\\b"+a,returnBegin:!0,relevance:0,end:".",contains:[{ +className:"identifier",begin:a,relevance:0}]}],b=[{className:"module", +begin:"\\b"+a,returnBegin:!0,end:".",relevance:0,contains:[{ +className:"identifier",begin:a,relevance:0}]}],m={className:"function", +relevance:0,keywords:r,variants:[{begin:"\\s(\\(\\.?.*?\\)|"+n+")\\s*=>", +end:"\\s*=>",returnBegin:!0,relevance:0,contains:[{className:"params", +variants:[{begin:n},{ +begin:"~?[a-z$_][0-9a-zA-Z$_]*(\\s*:\\s*[a-z$_][0-9a-z$_]*(\\(\\s*('?[a-z$_][0-9a-z$_]*\\s*(,'?[a-z$_][0-9a-z$_]*\\s*)*)?\\))?){0,2}" +},{begin:/\(\s*\)/}]}]},{begin:"\\s\\(\\.?[^;\\|]*\\)\\s*=>",end:"\\s=>", +returnBegin:!0,relevance:0,contains:[{className:"params",relevance:0,variants:[{ +begin:n,end:"(,|\\n|\\))",relevance:0,contains:[c,{className:"typing",begin:":", +end:"(,|\\n)",returnBegin:!0,relevance:0,contains:b}]}]}]},{ +begin:"\\(\\.\\s"+n+"\\)\\s*=>"}]};g.push(m);const d={className:"constructor", +begin:a+"\\(",end:"\\)",illegal:"\\n",keywords:r, +contains:[e.QUOTE_STRING_MODE,c,{className:"params",begin:"\\b"+n}]},u={ +className:"pattern-match",begin:"\\|",returnBegin:!0,keywords:r,end:"=>", +relevance:0,contains:[d,c,{relevance:0,className:"constructor",begin:a}]},v={ +className:"module-access",keywords:r,returnBegin:!0,variants:[{ +begin:"\\b("+a+"\\.)+"+n},{begin:"\\b("+a+"\\.)+\\(",end:"\\)",returnBegin:!0, +contains:[m,{begin:"\\(",end:"\\)",relevance:0,skip:!0}].concat(g)},{ +begin:"\\b("+a+"\\.)+\\{",end:/\}/}],contains:g};return b.push(v),{ +name:"ReasonML",aliases:["re"],keywords:r,illegal:"(:-|:=|\\$\\{|\\+=)", +contains:[e.COMMENT("/\\*","\\*/",{illegal:"^(#,\\/\\/)"}),{ +className:"character",begin:"'(\\\\[^']+|[^'])'",illegal:"\\n",relevance:0 +},e.QUOTE_STRING_MODE,{className:"literal",begin:"\\(\\)",relevance:0},{ +className:"literal",begin:"\\[\\|",end:"\\|\\]",relevance:0,contains:o},{ +className:"literal",begin:"\\[",end:"\\]",relevance:0,contains:o},d,{ +className:"operator",begin:i,illegal:"--\x3e",relevance:0 +},t,e.C_LINE_COMMENT_MODE,u,m,{className:"module-def", +begin:"\\bmodule\\s+"+n+"\\s+"+a+"\\s+=\\s+\\{",end:/\}/,returnBegin:!0, +keywords:r,relevance:0,contains:[{className:"module",relevance:0,begin:a},{ +begin:/\{/,end:/\}/,relevance:0,skip:!0}].concat(g)},v]}}})() +;hljs.registerLanguage("reasonml",e)})();/*! `javascript` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","module","global"],i=[].concat(r,t,s) +;return o=>{const l=o.regex,b=e,d={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,t=e.input[a] +;if("<"===t||","===t)return void n.ignoreMatch();let s +;">"===t&&(((e,{after:n})=>{const a="",M={ +match:[/const|var|let/,/\s+/,b,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(C)], +keywords:"async",className:{1:"keyword",3:"title.function"},contains:[S]} +;return{name:"Javascript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ +PARAMS_CONTAINS:p,CLASS_REFERENCE:R},illegal:/#(?![$_A-z])/, +contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ +label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,y,N,_,h,{match:/\$\d+/},E,R,{ +className:"attr",begin:b+l.lookahead(":"),relevance:0},M,{ +begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[h,o.REGEXP_MODE,{ +className:"function",begin:C,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, +excludeEnd:!0,keywords:g,contains:p}]}]},{begin:/,/,relevance:0},{match:/\s+/, +relevance:0},{variants:[{begin:"<>",end:""},{ +match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:d.begin, +"on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ +begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},O,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[S,o.inherit(o.TITLE_MODE,{begin:b, +className:"title.function"})]},{match:/\.\.\./,relevance:0},x,{match:"\\$"+b, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[S]},k,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, +className:"variable.constant"},w,T,{match:/\$[(.]/}]}}})() +;hljs.registerLanguage("javascript",e)})();/*! `sql` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const r=e.regex,t=e.COMMENT("--","$"),n=["true","false","unknown"],a=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],i=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],s=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],o=i,c=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!i.includes(e))),l={ +begin:r.concat(/\b/,r.either(...o),/\s*\(/),relevance:0,keywords:{built_in:o}} +;return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ +$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:r,when:t}={})=>{const n=t +;return r=r||[],e.map((e=>e.match(/\|\d+$/)||r.includes(e)?e:n(e)?e+"|0":e)) +})(c,{when:e=>e.length<3}),literal:n,type:a, +built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"] +},contains:[{begin:r.either(...s),relevance:0,keywords:{$pattern:/[\w\.]+/, +keyword:c.concat(s),literal:n,type:a}},{className:"type", +begin:r.either("double precision","large object","with timezone","without timezone") +},l,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{ +begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{ +begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,{className:"operator", +begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}})() +;hljs.registerLanguage("sql",e)})();/*! `bash` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const s=e.regex,t={},n={begin:/\$\{/, +end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]};Object.assign(t,{ +className:"variable",variants:[{ +begin:s.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},n]});const a={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},i={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,t,a]};a.contains.push(c);const o={begin:/\$?\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t] +},r=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/, +keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], +literal:["true","false"], +built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"] +},contains:[r,e.SHEBANG(),l,o,e.HASH_COMMENT_MODE,i,{match:/(\/[a-z._-]+)+/},c,{ +className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},t]}}})() +;hljs.registerLanguage("bash",e)})();/*! `shell` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var s=(()=>{"use strict";return s=>({name:"Shell Session", +aliases:["console","shellsession"],contains:[{className:"meta.prompt", +begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/, +subLanguage:"bash"}}]})})();hljs.registerLanguage("shell",s)})();/*! `plaintext` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var t=(()=>{"use strict";return t=>({name:"Plain text", +aliases:["text","txt"],disableAutodetect:!0})})() +;hljs.registerLanguage("plaintext",t)})();/*! `graphql` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=e.regex;return{name:"GraphQL", +aliases:["gql"],case_insensitive:!0,disableAutodetect:!1,keywords:{ +keyword:["query","mutation","subscription","type","input","schema","directive","interface","union","scalar","fragment","enum","on"], +literal:["true","false","null"]}, +contains:[e.HASH_COMMENT_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{ +scope:"punctuation",match:/[.]{3}/,relevance:0},{scope:"punctuation", +begin:/[\!\(\)\:\=\[\]\{\|\}]{1}/,relevance:0},{scope:"variable",begin:/\$/, +end:/\W/,excludeEnd:!0,relevance:0},{scope:"meta",match:/@\w+/,excludeEnd:!0},{ +scope:"symbol",begin:a.concat(/[_A-Za-z][_0-9A-Za-z]*/,a.lookahead(/\s*:/)), +relevance:0}],illegal:[/[;<']/,/BEGIN/]}}})();hljs.registerLanguage("graphql",e) +})();/*! `ocaml` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>({name:"OCaml",aliases:["ml"], +keywords:{$pattern:"[a-z_]\\w*!?", +keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value", +built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref", +literal:"true false"},illegal:/\/\/|>>/,contains:[{className:"literal", +begin:"\\[(\\|\\|)?\\]|\\(\\)",relevance:0},e.COMMENT("\\(\\*","\\*\\)",{ +contains:["self"]}),{className:"symbol",begin:"'[A-Za-z_](?!')[\\w']*"},{ +className:"type",begin:"`[A-Z][\\w']*"},{className:"type", +begin:"\\b[A-Z][\\w']*",relevance:0},{begin:"[a-z_]\\w*'[\\w']*",relevance:0 +},e.inherit(e.APOS_STRING_MODE,{className:"string",relevance:0 +}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:"number", +begin:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)", +relevance:0},{begin:/->/}]})})();hljs.registerLanguage("ocaml",e)})();/*! `json` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const a=["true","false","null"],n={ +scope:"literal",beginKeywords:a.join(" ")};return{name:"JSON",keywords:{ +literal:a},contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/, +relevance:1.01},{match:/[{}[\],:]/,className:"punctuation",relevance:0 +},e.QUOTE_STRING_MODE,n,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE], +illegal:"\\S"}}})();hljs.registerLanguage("json",e)})();/*! `python` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,i=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],s={ +$pattern:/[A-Za-z]\w+|__\w+__/,keyword:i, +built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"], +literal:["__debug__","Ellipsis","False","None","NotImplemented","True"], +type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"] +},t={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/, +end:/\}/,keywords:s,illegal:/#/},l={begin:/\{\{/,relevance:0},b={ +className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, +contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{ +begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, +end:/"""/,contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([uU]|[rR])'/,end:/'/, +relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ +begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, +end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, +contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] +},o="[0-9](_?[0-9])*",c=`(\\b(${o}))?\\.(${o})|\\b(${o})\\.`,d="\\b|"+i.join("|"),g={ +className:"number",relevance:0,variants:[{ +begin:`(\\b(${o})|(${c}))[eE][+-]?(${o})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{ +begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{ +begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})` +},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${o})[jJ](?=${d})` +}]},p={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:s, +contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={ +className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/, +end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:s, +contains:["self",t,g,b,e.HASH_COMMENT_MODE]}]};return r.contains=[b,g,t],{ +name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:s, +illegal:/(<\/|->|\?)|=>/,contains:[t,g,{begin:/\bself\b/},{beginKeywords:"if", +relevance:0},b,p,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,a],scope:{ +1:"keyword",3:"title.function"},contains:[m]},{variants:[{ +match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{match:[/\bclass/,/\s+/,a]}], +scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{ +className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[g,m,b]}]}}})() +;hljs.registerLanguage("python",e)})();/*! `xml` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{ +const a=e.regex,n=a.concat(/[\p{L}_]/u,a.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),s={ +className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},t={begin:/\s/, +contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] +},i=e.inherit(t,{begin:/\(/,end:/\)/}),c=e.inherit(e.APOS_STRING_MODE,{ +className:"string"}),l=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),r={ +endsWithParent:!0,illegal:/`]+/}]}]}]};return{ +name:"HTML, XML", +aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], +case_insensitive:!0,unicodeRegex:!0,contains:[{className:"meta",begin://,relevance:10,contains:[t,l,c,i,{begin:/\[/,end:/\]/,contains:[{ +className:"meta",begin://,contains:[t,i,l,c]}]}] +},e.COMMENT(//,{relevance:10}),{begin://, +relevance:10},s,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/, +relevance:10,contains:[l]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"style"},contains:[r],starts:{ +end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"script"},contains:[r],starts:{ +end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ +className:"tag",begin:/<>|<\/>/},{className:"tag", +begin:a.concat(//,/>/,/\s/)))), +end:/\/?>/,contains:[{className:"name",begin:n,relevance:0,starts:r}]},{ +className:"tag",begin:a.concat(/<\//,a.lookahead(a.concat(n,/>/))),contains:[{ +className:"name",begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}} +})();hljs.registerLanguage("xml",e)})();/*! `markdown` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const n={begin:/<\/?[A-Za-z_]/, +end:">",subLanguage:"xml",relevance:0},a={variants:[{begin:/\[.+?\]\[.*?\]/, +relevance:0},{ +begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, +relevance:2},{ +begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), +relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ +begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/ +},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, +returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", +excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", +end:"\\]",excludeBegin:!0,excludeEnd:!0}]},i={className:"strong",contains:[], +variants:[{begin:/_{2}(?!\s)/,end:/_{2}/},{begin:/\*{2}(?!\s)/,end:/\*{2}/}] +},s={className:"emphasis",contains:[],variants:[{begin:/\*(?![*\s])/,end:/\*/},{ +begin:/_(?![_\s])/,end:/_/,relevance:0}]},c=e.inherit(i,{contains:[] +}),t=e.inherit(s,{contains:[]});i.contains.push(t),s.contains.push(c) +;let g=[n,a];return[i,s,c,t].forEach((e=>{e.contains=e.contains.concat(g) +})),g=g.concat(i,s),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ +className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:g},{ +begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", +contains:g}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", +end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:g, +end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ +begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ +begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", +contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ +begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ +className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ +className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})() +;hljs.registerLanguage("markdown",e)})();/*! `c` grammar compiled for Highlight.js 11.7.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const n=e.regex,t=e.COMMENT("//","$",{ +contains:[{begin:/\\\n/}] +}),s="[a-zA-Z_]\\w*::",a="(decltype\\(auto\\)|"+n.optional(s)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",r={ +className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{ +match:/\batomic_[a-z]{3,6}\b/}]},i={className:"string",variants:[{ +begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},l={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},o={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},e.inherit(i,{className:"string"}),{ +className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},c={ +className:"title",begin:n.optional(s)+e.IDENT_RE,relevance:0 +},d=n.optional(s)+e.IDENT_RE+"\\s*\\(",u={ +keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"], +type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","const","static","complex","bool","imaginary"], +literal:"true false NULL", +built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" +},g=[o,r,t,e.C_BLOCK_COMMENT_MODE,l,i],m={variants:[{begin:/=/,end:/;/},{ +begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], +keywords:u,contains:g.concat([{begin:/\(/,end:/\)/,keywords:u, +contains:g.concat(["self"]),relevance:0}]),relevance:0},p={ +begin:"("+a+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, +keywords:u,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)", +keywords:u,relevance:0},{begin:d,returnBegin:!0,contains:[e.inherit(c,{ +className:"title.function"})],relevance:0},{relevance:0,match:/,/},{ +className:"params",begin:/\(/,end:/\)/,keywords:u,relevance:0, +contains:[t,e.C_BLOCK_COMMENT_MODE,i,l,r,{begin:/\(/,end:/\)/,keywords:u, +relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,i,l,r]}] +},r,t,e.C_BLOCK_COMMENT_MODE,o]};return{name:"C",aliases:["h"],keywords:u, +disableAutodetect:!0,illegal:"=]/,contains:[{ +beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:o, +strings:i,keywords:u}}}})();hljs.registerLanguage("c",e)})(); diff --git a/assets/js/odoc_search.js b/assets/js/odoc_search.js new file mode 100644 index 0000000..2c78354 --- /dev/null +++ b/assets/js/odoc_search.js @@ -0,0 +1,72 @@ +/* The browsers interpretation of the CORS origin policy prevents to run + webworkers from javascript files fetched from the file:// protocol. This hack + is to workaround this restriction. */ +function createWebWorker() { + var blobContents = ["importScripts(\"" + search_urls.join("\",\"") + "\");"]; + var blob = new Blob(blobContents, { type: "application/javascript" }); + var blobUrl = URL.createObjectURL(blob); + + var worker = new Worker(blobUrl); + URL.revokeObjectURL(blobUrl); + + return worker; +} + +var worker; +var waiting = 0; + +function wait() { + waiting = waiting + 1; + document.querySelector(".search-snake").classList.add("search-busy"); +} + +function stop_waiting() { + if (waiting > 0) waiting = waiting - 1; + else waiting = 0; + if (waiting == 0) { + document.querySelector(".search-snake").classList.remove("search-busy"); + } +} + +window.onload = function () { + document.querySelector(".search-bar").addEventListener("focus", (ev) => { + if (typeof worker == "undefined") { + worker = createWebWorker(); + worker.onmessage = (e) => { + stop_waiting(); + let results = e.data; + let search_results = document.querySelector(".search-result"); + search_results.innerHTML = ""; + let f = (entry) => { + let search_result = document.createElement("a"); + console.log(entry); + search_result.classList.add("search-entry"); + // MANUAL EDIT: change the URL to match our scheme: + // ie. no package level in URL, instead replace it with a version level + // See https://github.com/art-w/sherlodoc/issues/41 for a discussion on this + search_result.href = + // removing leading "../" that would take us back to the package level + // The url is instead relative to the library toplevel + base_url.replace(/^\.\.\//, "") + + // Removing package-name from full URL (given relative to the package level) + entry.url.replace(/^patricia\-tree\//, ""); + search_result.innerHTML = entry.html; + search_results.appendChild(search_result); + }; + results.forEach(f); + let search_request = document.querySelector(".search-bar").value; + if (results.length == 0 && search_request != "") { + let no_result = document.createElement("div"); + no_result.classList.add("search-no-result"); + no_result.innerText = "No result..."; + search_results.appendChild(no_result); + } + }; + } + }); + + document.querySelector(".search-bar").addEventListener("input", (ev) => { + wait(); + worker.postMessage(ev.target.value); + }); +} diff --git a/assets/js/sherlodoc-db/patricia-tree.main.js b/assets/js/sherlodoc-db/patricia-tree.main.js new file mode 100644 index 0000000..60a4490 --- /dev/null +++ b/assets/js/sherlodoc-db/patricia-tree.main.js @@ -0,0 +1 @@ +function sherlodoc_db () { return "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"; } diff --git a/assets/js/sherlodoc-db/patricia-tree.v0.10.0.js b/assets/js/sherlodoc-db/patricia-tree.v0.10.0.js new file mode 100644 index 0000000..60a4490 --- /dev/null +++ b/assets/js/sherlodoc-db/patricia-tree.v0.10.0.js @@ -0,0 +1 @@ +function sherlodoc_db () { return "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"; } diff --git a/assets/js/sherlodoc-db/patricia-tree.v0.9.0.js b/assets/js/sherlodoc-db/patricia-tree.v0.9.0.js new file mode 100644 index 0000000..0643477 --- /dev/null +++ b/assets/js/sherlodoc-db/patricia-tree.v0.9.0.js @@ -0,0 +1 @@ +function sherlodoc_db () { return "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"; } diff --git a/assets/js/sherlodoc.js b/assets/js/sherlodoc.js new file mode 100644 index 0000000..b87bc52 --- /dev/null +++ b/assets/js/sherlodoc.js @@ -0,0 +1,1844 @@ +// Generated by js_of_ocaml +//# buildInfo:effects=false, kind=exe, use-js-string=true, version=5.7.2 +(function(a){typeof +globalThis!=="object"&&(this?b():(a.defineProperty(a.prototype,"_T_",{configurable:true,get:b}),_T_));function +b(){var +b=this||self;b.globalThis=b;delete +a.prototype._T_}}(Object));(function(l){"use strict";var +ef="Sys_error",u=0x80,dS="ENOTEMPTY",aQ=" ",ca="compare: functional value",ed="union all",ee="EEXIST",b7=1255,d5="entry-name",b$="mkdir",aa=1000,ec=1073741823,b6=" : flags Open_text and Open_binary are not compatible",et="console",b_="fs",b9=5795659,d4="/static/",dR="Stack_overflow",b5=": Not a directory",cf="ENOENT",Q=0xff,eb="Undefined_recursive_module",d3="Assert_failure",H=0x8000,ea=0x800,es=0x7ff0,dQ=" : is a directory",d2=0xdfff,d$="Division_by_zero",dP=".",er="End_of_file",d1="OCAMLRUNPARAM",ce=10000,aR="query/priority_queue.ml",d0=": closedir failed",ab=0x3f,eq="Out_of_memory",b4="db/string_automata.ml",dZ="Not_found",cd=" : file already exists",cj="Failure",bj=": No such file or directory",ax=128,bk="Unix.Unix_error",ep="^",cc=255,eo="length",aw=256,ci="ENOTDIR",G="/",b3="index out of bounds",dO=0xFF,b2=252,dY="Invalid_argument",$=254,bg="Set.bal",dN=": file descriptor already closed",b1="EBADF",aj=0xffffff,dM="Marshal.from_bytes",dX=1027,aP=1024,dW=246,bi=0x7F,en="Pervasives.do_at_exit",dL=12520,cb=" : flags Open_rdonly and Open_wronly are not compatible",em=65536,b0=0x3F,ch=0xf,dV=512,ek="Match_failure",el="closedir",dU=1026,dT="inter all",d_="class",bf=250,d9=">",e="",b8="rmdir",d8="([^/]+)",cg="fut",bZ="jsError",aO='"',P=0xffff,ej="fd ",dK=0xdc00,d6="cons",d7="Sys_blocked_io",c=248,ei="@",dI="span",dJ="buffer.ml",eh=0xe0,bh="_bigarr02",eg=0xf0;function +a1(a,b,c){var +d=String.fromCharCode;if(b==0&&c<=4096&&c==a.length)return d.apply(null,a);var +f=e;for(;0=c.l||c.t==2&&e>=c.c.length)){c.c=a.t==4?a1(a.c,b,e):b==0&&a.c.length==e?a.c:a.c.substr(b,e);c.t=c.c.length==c.l?0:2}else if(c.t==2&&d==c.c.length){c.c+=a.t==4?a1(a.c,b,e):b==0&&a.c.length==e?a.c:a.c.substr(b,e);c.t=c.c.length==c.l?0:2}else{if(c.t!=4)bo(c);var +g=a.c,h=c.c;if(a.t==4)if(d<=b)for(var +f=0;f=0;f--)h[d+f]=g[b+f];else{var +i=Math.min(e,g.length-b);for(var +f=0;f>=1;if(a==0)return d;b+=b;c++;if(c==9)b.slice(0,1)}}function +aU(a){if(a.t==2)a.c+=eT(a.l-a.c.length,"\0");else +a.c=a1(a.c,0,a.c.length);a.t=0}function +cz(a){if(a.length<24){for(var +b=0;b127)return false;return true}else +return!/[^\x00-\x7f]/.test(a)}function +eX(a){for(var +k=e,d=e,h,g,i,b,c=0,j=a.length;cdV){d.substr(0,1);k+=d;d=e;k+=a.slice(c,f)}else +d+=a.slice(c,f);if(f==j)break;c=f}b=1;if(++c=0xd7ff&&b<0xe000)b=2}else{b=3;if(++c0x10ffff)b=3}}}}}if(b<4){c-=b;d+="\ufffd"}else if(b>P)d+=String.fromCharCode(0xd7c0+(b>>10),dK+(b&0x3FF));else +d+=String.fromCharCode(b);if(d.length>aP){d.substr(0,1);k+=d;d=e}}return k+d}function +R(a,b,c){this.t=a;this.c=b;this.l=c}R.prototype.toString=function(){switch(this.t){case +9:return this.c;default:aU(this);case +0:if(cz(this.c)){this.t=9;return this.c}this.t=8;case +8:return this.c}};R.prototype.toUtf16=function(){var +a=this.toString();if(this.t==9)return a;return eX(a)};R.prototype.slice=function(){var +a=this.t==4?this.c.slice():this.c;return new +R(this.t,a,this.l)};function +eC(a){return new +R(0,a,a.length)}function +T(a){return a}function +I(a){return eC(T(a))}function +al(a,b,c,d,e){S(I(a),b,c,d,e);return 0}function +g2(a,b){switch(a.t&6){default:if(b>=a.c.length)return 0;case +0:return a.c.charCodeAt(b);case +4:return a.c[b]}}function +eD(a,b,c){c&=Q;if(a.t!=4){if(b==a.c.length){a.c+=String.fromCharCode(c);if(b+1==a.l)a.t=0;return 0}bo(a)}a.c[b]=c;return 0}function +az(d,c){var +f=d.l>=0?d.l:d.l=d.length,e=c.length,b=f-e;if(b==0)return d.apply(null,c);else if(b<0){var +a=d.apply(null,c.slice(0,f));if(typeof +a!=="function")return a;return az(a,c.slice(f))}else{switch(b){case +1:{var +a=function(a){var +f=new +Array(e+1);for(var +b=0;b>>0>=a.length-1)aT();return a}function +eK(a){return 0}var +hP=Math.log2&&Math.log2(1.1235582092889474E+307)==1020;function +hO(a){if(hP)return Math.floor(Math.log2(a));var +b=0;if(a==0)return-Infinity;if(a>=1)while(a>=2){a/=2;b++}else +while(a<1){a*=2;b--}return b}function +cq(a){var +b=new +Float32Array(1);b[0]=a;var +c=new +Int32Array(b.buffer);return c[0]|0}var +eJ=Math.pow(2,-24);function +eQ(a){throw a}function +cv(){eQ(r.Division_by_zero)}function +d(a,b,c){this.lo=a&aj;this.mi=b&aj;this.hi=c&P}d.prototype.caml_custom="_j";d.prototype.copy=function(){return new +d(this.lo,this.mi,this.hi)};d.prototype.ucompare=function(a){if(this.hi>a.hi)return 1;if(this.hia.mi)return 1;if(this.mia.lo)return 1;if(this.loc)return 1;if(ba.mi)return 1;if(this.mia.lo)return 1;if(this.lo>24),c=-this.hi+(b>>24);return new +d(a,b,c)};d.prototype.add=function(a){var +b=this.lo+a.lo,c=this.mi+a.mi+(b>>24),e=this.hi+a.hi+(c>>24);return new +d(b,c,e)};d.prototype.sub=function(a){var +b=this.lo-a.lo,c=this.mi-a.mi+(b>>24),e=this.hi-a.hi+(c>>24);return new +d(b,c,e)};d.prototype.mul=function(a){var +b=this.lo*a.lo,c=(b*eJ|0)+this.mi*a.lo+this.lo*a.mi,e=(c*eJ|0)+this.hi*a.lo+this.mi*a.mi+this.lo*a.hi;return new +d(b,c,e)};d.prototype.isZero=function(){return(this.lo|this.mi|this.hi)==0};d.prototype.isNeg=function(){return this.hi<<16<0};d.prototype.and=function(a){return new +d(this.lo&a.lo,this.mi&a.mi,this.hi&a.hi)};d.prototype.or=function(a){return new +d(this.lo|a.lo,this.mi|a.mi,this.hi|a.hi)};d.prototype.xor=function(a){return new +d(this.lo^a.lo,this.mi^a.mi,this.hi^a.hi)};d.prototype.shift_left=function(a){a=a&63;if(a==0)return this;if(a<24)return new +d(this.lo<>24-a,this.hi<>24-a);if(a<48)return new +d(0,this.lo<>48-a);return new +d(0,0,this.lo<>a|this.mi<<24-a,this.mi>>a|this.hi<<24-a,this.hi>>a);if(a<48)return new +d(this.mi>>a-24|this.hi<<48-a,this.hi>>a-24,0);return new +d(this.hi>>a-48,0,0)};d.prototype.shift_right=function(a){a=a&63;if(a==0)return this;var +c=this.hi<<16>>16;if(a<24)return new +d(this.lo>>a|this.mi<<24-a,this.mi>>a|c<<24-a,this.hi<<16>>a>>>16);var +b=this.hi<<16>>31;if(a<48)return new +d(this.mi>>a-24|this.hi<<48-a,this.hi<<16>>a-24>>16,b&P);return new +d(this.hi<<16>>a-32,b,b)};d.prototype.lsl1=function(){this.hi=this.hi<<1|this.mi>>23;this.mi=(this.mi<<1|this.lo>>23)&aj;this.lo=this.lo<<1&aj};d.prototype.lsr1=function(){this.lo=(this.lo>>>1|this.mi<<23)&aj;this.mi=(this.mi>>>1|this.hi<<23)&aj;this.hi=this.hi>>>1};d.prototype.udivmod=function(a){var +e=0,c=this.copy(),b=a.copy(),f=new +d(0,0,0);while(c.ucompare(b)>0){e++;b.lsl1()}while(e>=0){e--;f.lsl1();if(c.ucompare(b)>=0){f.lo++;c=c.sub(b)}b.lsr1()}return{quotient:f,modulus:c}};d.prototype.div=function(a){var +b=this;if(a.isZero())cv();var +d=b.hi^a.hi;if(b.hi&H)b=b.neg();if(a.hi&H)a=a.neg();var +c=b.udivmod(a).quotient;if(d&H)c=c.neg();return c};d.prototype.mod=function(a){var +b=this;if(a.isZero())cv();var +d=b.hi;if(b.hi&H)b=b.neg();if(a.hi&H)a=a.neg();var +c=b.udivmod(a).modulus;if(d&H)c=c.neg();return c};d.prototype.toInt=function(){return this.lo|this.mi<<24};d.prototype.toFloat=function(){return(this.hi<<16)*Math.pow(2,32)+this.mi*Math.pow(2,24)+this.lo};d.prototype.toArray=function(){return[this.hi>>8,this.hi&Q,this.mi>>16,this.mi>>8&Q,this.mi&Q,this.lo>>16,this.lo>>8&Q,this.lo&Q]};d.prototype.lo32=function(){return this.lo|(this.mi&Q)<<24};d.prototype.hi32=function(){return this.mi>>>8&P|this.hi<<16};function +br(a,b,c){return new +d(a,b,c)}function +bq(a){if(!isFinite(a)){if(isNaN(a))return br(1,0,es);return a>0?br(0,0,es):br(0,0,0xfff0)}var +f=a==0&&1/a==-Infinity?H:a>=0?0:H;if(f)a=-a;var +b=hO(a)+1023;if(b<=0){b=0;a/=Math.pow(2,-dU)}else{a/=Math.pow(2,b-dX);if(a<16){a*=2;b-=1}if(b==0)a/=2}var +d=Math.pow(2,24),c=a|0;a=(a-c)*d;var +e=a|0;a=(a-e)*d;var +g=a|0;c=c&ch|f|b<<4;return br(g,e,c)}function +aW(a){return a.toArray()}function +eB(a,b,c){a.write(32,b.dims.length);a.write(32,b.kind|b.layout<<8);if(b.caml_custom==bh)for(var +d=0;d>4;if(d==2047)return(f|g|c&ch)==0?c&H?-Infinity:Infinity:NaN;var +e=Math.pow(2,-24),b=(f*e+g)*e+(c&ch);if(d>0){b+=16;b*=Math.pow(2,d-dX)}else +b*=Math.pow(2,-dU);if(c&H)b=-b;return b}function +cl(a){var +d=a.length,c=1;for(var +b=0;b>>24&Q|(b&P)<<8,b>>>16&P)}function +cs(a){return a.hi32()}function +ct(a){return a.lo32()}var +gY=bh;function +ac(a,b,c,d){this.kind=a;this.layout=b;this.dims=c;this.data=d}ac.prototype.caml_custom=gY;ac.prototype.offset=function(a){var +c=0;if(typeof +a==="number")a=[a];if(!(a +instanceof +Array))o("bigarray.js: invalid offset");if(this.dims.length!=a.length)o("Bigarray.get/set: bad number of dimensions");if(this.layout==0)for(var +b=0;b=this.dims[b])aT();c=c*this.dims[b]+a[b]}else +for(var +b=this.dims.length-1;b>=0;b--){if(a[b]<1||a[b]>this.dims[b])aT();c=c*this.dims[b]+(a[b]-1)}return c};ac.prototype.get=function(a){switch(this.kind){case +7:var +d=this.data[a*2+0],b=this.data[a*2+1];return hh(d,b);case +10:case +11:var +e=this.data[a*2+0],c=this.data[a*2+1];return[$,e,c];default:return this.data[a]}};ac.prototype.set=function(a,b){switch(this.kind){case +7:this.data[a*2+0]=ct(b);this.data[a*2+1]=cs(b);break;case +10:case +11:this.data[a*2+0]=b[1];this.data[a*2+1]=b[2];break;default:this.data[a]=b;break}return 0};ac.prototype.fill=function(a){switch(this.kind){case +7:var +c=ct(a),e=cs(a);if(c==e)this.data.fill(c);else +for(var +b=0;be)return 1;if(d!=e){if(!b)return NaN;if(d==d)return 1;if(e==e)return-1}}break;case +7:for(var +c=0;ca.data[c+1])return 1;if(this.data[c]>>>0>>0)return-1;if(this.data[c]>>>0>a.data[c]>>>0)return 1}break;case +2:case +3:case +4:case +5:case +6:case +8:case +9:case +12:for(var +c=0;ca.data[c])return 1}break}return 0};function +ay(a,b,c,d){this.kind=a;this.layout=b;this.dims=c;this.data=d}ay.prototype=new +ac();ay.prototype.offset=function(a){if(typeof +a!=="number")if(a +instanceof +Array&&a.length==1)a=a[0];else +o("Ml_Bigarray_c_1_1.offset");if(a<0||a>=this.dims[0])aT();return a};ay.prototype.get=function(a){return this.data[a]};ay.prototype.set=function(a,b){this.data[a]=b;return 0};ay.prototype.fill=function(a){this.data.fill(a);return 0};function +ex(a,b,c,d){var +e=ez(a);if(cl(c)*e!=d.length)o("length doesn't match dims");if(b==0&&c.length==1&&e==1)return new +ay(a,b,c,d);return new +ac(a,b,c,d)}function +m(a){if(!r.Failure)r.Failure=[c,B(cj),-3];cu(r.Failure,a)}function +ey(a,b,c){var +k=a.read32s();if(k<0||k>16)m("input_value: wrong number of bigarray dimensions");var +s=a.read32s(),l=s&Q,r=s>>8&1,j=[];if(c==bh)for(var +d=0;d>>32-15;b=bv(b,0x1b873593);a^=b;a=a<<13|a>>>32-13;return(a+(a<<2)|0)+(0xe6546b64|0)|0}function +hb(a,b){a=s(a,ct(b));a=s(a,cs(b));return a}function +co(a,b){return hb(a,bq(b))}function +eA(a){var +c=cl(a.dims),d=0;switch(a.kind){case +2:case +3:case +12:if(c>aw)c=aw;var +e=0,b=0;for(b=0;b+4<=a.data.length;b+=4){e=a.data[b+0]|a.data[b+1]<<8|a.data[b+2]<<16|a.data[b+3]<<24;d=s(d,e)}e=0;switch(c&3){case +3:e=a.data[b+2]<<16;case +2:e|=a.data[b+1]<<8;case +1:e|=a.data[b+0];d=s(d,e)}break;case +4:case +5:if(c>ax)c=ax;var +e=0,b=0;for(b=0;b+2<=a.data.length;b+=2){e=a.data[b+0]|a.data[b+1]<<16;d=s(d,e)}if((c&1)!=0)d=s(d,a.data[b]);break;case +6:if(c>64)c=64;for(var +b=0;b64)c=64;for(var +b=0;b32)c=32;c*=2;for(var +b=0;b64)c=64;for(var +b=0;b32)c=32;for(var +b=0;b0?f(b,a,d):f(a,b,d);if(d&&e!=e)return c;if(+e!=+e)return+e;if((e|0)!=0)return e|0}return c}function +bu(a){return typeof +a==="string"&&!/[^\x00-\xff]/.test(a)}function +bt(a){return a +instanceof +R}function +eF(a){if(typeof +a==="number")return aa;else if(bt(a))return b2;else if(bu(a))return 1252;else if(a +instanceof +Array&&a[0]===a[0]>>>0&&a[0]<=cc){var +b=a[0]|0;return b==$?0:b}else if(a +instanceof +String)return dL;else if(typeof +a=="string")return dL;else if(a +instanceof +Number)return aa;else if(a&&a.caml_custom)return b7;else if(a&&a.compare)return 1256;else if(typeof +a=="function")return 1247;else if(typeof +a=="symbol")return 1251;return 1001}function +aX(a,b){if(ab?1:0}function +g1(a,b){a.t&6&&aU(a);b.t&6&&aU(b);return a.cb.c?1:0}function +bn(a,b,c){var +f=[];for(;;){if(!(c&&a===b)){var +e=eF(a);if(e==bf){a=a[1];continue}var +g=eF(b);if(g==bf){b=b[1];continue}if(e!==g){if(e==aa){if(g==b7)return eE(a,b,-1,c);return-1}if(g==aa){if(e==b7)return eE(b,a,1,c);return 1}return eb)return 1;if(a!=b){if(!c)return NaN;if(a==a)return 1;if(b==b)return-1}break;case +1001:if(ab)return 1;if(a!=b){if(!c)return NaN;if(a==a)return 1;if(b==b)return-1}break;case +1251:if(a!==b){if(!c)return NaN;return 1}break;case +1252:var +a=T(a),b=T(b);if(a!==b){if(ab)return 1}break;case +12520:var +a=a.toString(),b=b.toString();if(a!==b){if(ab)return 1}break;case +246:case +254:default:if(eK(e)){o("compare: continuation value");break}if(a.length!=b.length)return a.length1)f.push(a,b,1);break}}if(f.length==0)return 0;var +h=f.pop();b=f.pop();a=f.pop();if(h+10)if(b==0&&(c>=a.l||a.t==2&&c>=a.c.length))if(d==0){a.c=e;a.t=2}else{a.c=eT(c,String.fromCharCode(d));a.t=c==a.l?0:2}else{if(a.t!=4)bo(a);for(c+=b;b1)b.pop();break;case".":break;case"":break;default:b.push(d[c]);break}b.unshift(e[0]);b.orig=a;return b}function +hN(a){for(var +g=e,c=g,b,i,d=0,h=a.length;ddV){c.substr(0,1);g+=c;c=e;g+=a.slice(d,f)}else +c+=a.slice(d,f);if(f==h)break;d=f}if(b>6);c+=String.fromCharCode(u|b&ab)}else if(b<0xd800||b>=d2)c+=String.fromCharCode(eh|b>>12,u|b>>6&ab,u|b&ab);else if(b>=0xdbff||d+1==h||(i=a.charCodeAt(d+1))d2)c+="\xef\xbf\xbd";else{d++;b=(b<<10)+i-0x35fdc00;c+=String.fromCharCode(eg|b>>18,u|b>>12&ab,u|b>>6&ab,u|b&ab)}if(c.length>aP){c.substr(0,1);g+=c;c=e}}return g+c}function +K(a){return cz(a)?B(a):B(hN(a))}var +hR=["E2BIG","EACCES","EAGAIN",b1,"EBUSY","ECHILD","EDEADLK","EDOM",ee,"EFAULT","EFBIG","EINTR","EINVAL","EIO","EISDIR","EMFILE","EMLINK","ENAMETOOLONG","ENFILE","ENODEV",cf,"ENOEXEC","ENOLCK","ENOMEM","ENOSPC","ENOSYS",ci,dS,"ENOTTY","ENXIO","EPERM","EPIPE","ERANGE","EROFS","ESPIPE","ESRCH","EXDEV","EWOULDBLOCK","EINPROGRESS","EALREADY","ENOTSOCK","EDESTADDRREQ","EMSGSIZE","EPROTOTYPE","ENOPROTOOPT","EPROTONOSUPPORT","ESOCKTNOSUPPORT","EOPNOTSUPP","EPFNOSUPPORT","EAFNOSUPPORT","EADDRINUSE","EADDRNOTAVAIL","ENETDOWN","ENETUNREACH","ENETRESET","ECONNABORTED","ECONNRESET","ENOBUFS","EISCONN","ENOTCONN","ESHUTDOWN","ETOOMANYREFS","ETIMEDOUT","ECONNREFUSED","EHOSTDOWN","EHOSTUNREACH","ELOOP","EOVERFLOW"];function +X(a,b,c,d){var +f=hR.indexOf(a);if(f<0){if(d==null)d=-9999;f=[0,d]}var +g=[f,K(b||e),K(c||e)];return g}var +eN={};function +ae(a){return eN[a]}function +V(a,b){throw k([0,a].concat(b))}function +cm(a){if(!(a +instanceof +Uint8Array))a=new +Uint8Array(a);return new +R(4,a,a.length)}function +j(a){cu(r.Sys_error,a)}function +eR(a){j(a+bj)}function +a2(a){if(a.t!=4)bo(a);return a.c}function +ad(a){return a.l}function +eu(){}function +t(a){this.data=a}t.prototype=new +eu();t.prototype.constructor=t;t.prototype.truncate=function(a){var +b=this.data;this.data=v(a|0);S(b,0,this.data,0,a)};t.prototype.length=function(){return ad(this.data)};t.prototype.write=function(a,b,c,d){var +e=this.length();if(a+d>=e){var +f=v(a+d),g=this.data;this.data=f;S(g,0,this.data,0,e)}S(cm(b),c,this.data,a,d);return 0};t.prototype.read=function(a,b,c,d){var +e=this.length();if(a+d>=e)d=e-a;if(d){var +f=v(d|0);S(this.data,a,f,0,d);b.set(a2(f),c)}return d};function +ak(a,b,c){this.file=b;this.name=a;this.flags=c}ak.prototype.err_closed=function(){j(this.name+dN)};ak.prototype.length=function(){if(this.file)return this.file.length();this.err_closed()};ak.prototype.write=function(a,b,c,d){if(this.file)return this.file.write(a,b,c,d);this.err_closed()};ak.prototype.read=function(a,b,c,d){if(this.file)return this.file.read(a,b,c,d);this.err_closed()};ak.prototype.close=function(){this.file=undefined};function +a(a,b){this.content={};this.root=a;this.lookupFun=b}a.prototype.nm=function(a){return this.root+a};a.prototype.create_dir_if_needed=function(a){var +d=a.split(G),c=e;for(var +b=0;b>>0>=a.l)g0();return eD(a,b,c)}function +D(a,b){this.fs=require(b_);this.fd=a;this.flags=b}D.prototype=new +eu();D.prototype.constructor=D;D.prototype.truncate=function(a){try{this.fs.ftruncateSync(this.fd,a|0)}catch(f){j(f.toString())}};D.prototype.length=function(){try{return this.fs.fstatSync(this.fd).size}catch(f){j(f.toString())}};D.prototype.write=function(a,b,c,d){try{if(this.flags.isCharacterDevice)this.fs.writeSync(this.fd,b,c,d);else +this.fs.writeSync(this.fd,b,c,d,a)}catch(f){j(f.toString())}return 0};D.prototype.read=function(a,b,c,d){try{if(this.flags.isCharacterDevice)var +e=this.fs.readSync(this.fd,b,c,d);else +var +e=this.fs.readSync(this.fd,b,c,d,a);return e}catch(f){j(f.toString())}};D.prototype.close=function(){try{this.fs.closeSync(this.fd);return 0}catch(f){j(f.toString())}};function +n(a){this.fs=require(b_);this.root=a}n.prototype.nm=function(a){return this.root+a};n.prototype.exists=function(a){try{return this.fs.existsSync(this.nm(a))?1:0}catch(f){return 0}};n.prototype.isFile=function(a){try{return this.fs.statSync(this.nm(a)).isFile()?1:0}catch(f){j(f.toString())}};n.prototype.mkdir=function(a,b,c){try{this.fs.mkdirSync(this.nm(a),{mode:b});return 0}catch(f){this.raise_nodejs_error(f,c)}};n.prototype.rmdir=function(a,b){try{this.fs.rmdirSync(this.nm(a));return 0}catch(f){this.raise_nodejs_error(f,b)}};n.prototype.readdir=function(a,b){try{return this.fs.readdirSync(this.nm(a))}catch(f){this.raise_nodejs_error(f,b)}};n.prototype.is_dir=function(a){try{return this.fs.statSync(this.nm(a)).isDirectory()?1:0}catch(f){j(f.toString())}};n.prototype.unlink=function(a,b){try{var +c=this.fs.existsSync(this.nm(a))?1:0;this.fs.unlinkSync(this.nm(a));return c}catch(f){this.raise_nodejs_error(f,b)}};n.prototype.open=function(a,b,c){var +d=require("constants"),e=0;for(var +h +in +b)switch(h){case"rdonly":e|=d.O_RDONLY;break;case"wronly":e|=d.O_WRONLY;break;case"append":e|=d.O_WRONLY|d.O_APPEND;break;case"create":e|=d.O_CREAT;break;case"truncate":e|=d.O_TRUNC;break;case"excl":e|=d.O_EXCL;break;case"binary":e|=d.O_BINARY;break;case"text":e|=d.O_TEXT;break;case"nonblock":e|=d.O_NONBLOCK;break}try{var +f=this.fs.openSync(this.nm(a),e),g=this.fs.lstatSync(this.nm(a)).isCharacterDevice();b.isCharacterDevice=g;return new +D(f,b)}catch(f){this.raise_nodejs_error(f,c)}};n.prototype.rename=function(a,b,c){try{this.fs.renameSync(this.nm(a),this.nm(b))}catch(f){this.raise_nodejs_error(f,c)}};n.prototype.stat=function(a,b){try{var +c=this.fs.statSync(this.nm(a));return this.stats_from_js(c)}catch(f){this.raise_nodejs_error(f,b)}};n.prototype.lstat=function(a,b){try{var +c=this.fs.lstatSync(this.nm(a));return this.stats_from_js(c)}catch(f){this.raise_nodejs_error(f,b)}};n.prototype.symlink=function(a,b,c,d){try{this.fs.symlinkSync(this.nm(b),this.nm(c),a?"dir":"file");return 0}catch(f){this.raise_nodejs_error(f,d)}};n.prototype.readlink=function(a,b){try{var +c=this.fs.readlinkSync(this.nm(a),"utf8");return K(c)}catch(f){this.raise_nodejs_error(f,b)}};n.prototype.opendir=function(a,b){try{return this.fs.opendirSync(this.nm(a))}catch(f){this.raise_nodejs_error(f,b)}};n.prototype.raise_nodejs_error=function(a,b){var +c=ae(bk);if(b&&c){var +d=X(a.code,a.syscall,a.path,a.errno);V(c,d)}else +j(a.toString())};n.prototype.stats_from_js=function(a){var +b;if(a.isFile())b=0;else if(a.isDirectory())b=1;else if(a.isCharacterDevice())b=2;else if(a.isBlockDevice())b=3;else if(a.isSymbolicLink())b=4;else if(a.isFIFO())b=5;else if(a.isSocket())b=6;return[0,a.dev,a.ino,b,a.mode,a.nlink,a.uid,a.gid,a.rdev,a.size,a.atimeMs,a.mtimeMs,a.ctimeMs]};n.prototype.constructor=n;function +eI(a){var +b=cA(a);if(!b)return;return b[0]+G}var +bw=eI(aV)||m("unable to compute caml_root"),aG=[];if(a3())aG.push({path:bw,device:new +n(bw)});else +aG.push({path:bw,device:new +a(bw)});aG.push({path:d4,device:new +a(d4)});function +e0(a){var +g=hq(a),a=g.join(G),f=eW(a),c;for(var +e=0;e>>16;a=bv(a,0x85ebca6b|0);a^=a>>>13;a=bv(a,0xc2b2ae35|0);a^=a>>>16;return a}function +g9(a,b,c,d){var +j,k,l,h,g,f,e,i,m;h=b;if(h<0||h>aw)h=aw;g=a;f=c;j=[d];k=0;l=1;while(k0){e=j[k++];if(e&&e.caml_custom){if(aA[e.caml_custom]&&aA[e.caml_custom].hash){var +n=aA[e.caml_custom].hash(e);f=s(f,n);g--}}else if(e +instanceof +Array&&e[0]===(e[0]|0))switch(e[0]){case +248:f=s(f,e[2]);g--;break;case +250:j[--k]=e[1];break;default:if(eK(e[0]))break;var +o=e.length-1<<10|e[0];f=s(f,o);for(i=1,m=e.length;i=h)break;j[l++]=e[i]}break}else if(bt(e)){f=g_(f,e);g--}else if(bu(e)){f=hc(f,e);g--}else if(typeof +e==="string"){f=cp(f,e);g--}else if(e===(e|0)){f=s(f,e+e+1);g--}else if(typeof +e==="number"){f=co(f,e);g--}}f=ha(f);return f&0x3FFFFFFF}function +ev(a,b){this.s=T(a);this.i=b}ev.prototype={read8u:function(){return this.s.charCodeAt(this.i++)},read8s:function(){return this.s.charCodeAt(this.i++)<<24>>24},read16u:function(){var +b=this.s,a=this.i;this.i=a+2;return b.charCodeAt(a)<<8|b.charCodeAt(a+1)},read16s:function(){var +b=this.s,a=this.i;this.i=a+2;return b.charCodeAt(a)<<24>>16|b.charCodeAt(a+1)},read32u:function(){var +b=this.s,a=this.i;this.i=a+4;return(b.charCodeAt(a)<<24|b.charCodeAt(a+1)<<16|b.charCodeAt(a+2)<<8|b.charCodeAt(a+3))>>>0},read32s:function(){var +b=this.s,a=this.i;this.i=a+4;return b.charCodeAt(a)<<24|b.charCodeAt(a+1)<<16|b.charCodeAt(a+2)<<8|b.charCodeAt(a+3)},readstr:function(a){var +b=this.i;this.i=b+a;return B(this.s.substring(b,b+a))},readuint8array:function(a){var +c=new +Uint8Array(a),e=this.s,d=this.i;for(var +b=0;b>24},read16u:function(){var +b=this.s,a=this.i;this.i=a+2;return b[a]<<8|b[a+1]},read16s:function(){var +b=this.s,a=this.i;this.i=a+2;return b[a]<<24>>16|b[a+1]},read32u:function(){var +b=this.s,a=this.i;this.i=a+4;return(b[a]<<24|b[a+1]<<16|b[a+2]<<8|b[a+3])>>>0},read32s:function(){var +b=this.s,a=this.i;this.i=a+4;return b[a]<<24|b[a+1]<<16|b[a+2]<<8|b[a+3]},readstr:function(a){var +b=this.i;this.i=b+a;return cy(this.s.subarray(b,b+a))},readuint8array:function(a){var +b=this.i;this.i=b+a;return this.s.subarray(b,b+a)}};function +aB(a){return bs(aC(a))}function +he(d,b){function +f(a){var +b=d.read8u(),c=b&bi;while((b&u)!=0){b=d.read8u();var +e=c<<7;if(c!=e>>7)a[0]=true;c=e|b&bi}return c}var +x=d.read32u();switch(x){case +0x8495A6BE:var +w=20,o=0,h=d.read32u(),r=h,p=d.read32u(),s=d.read32u(),t=d.read32u();break;case +0x8495A6BD:var +w=d.read8u()&b0,o=1,a=[false],h=f(a),r=f(a),p=f(a),s=f(a),t=f(a);if(a[0])m("caml_input_value_from_reader: object too large to be read back on this platform");break;case +0x8495A6BF:m("caml_input_value_from_reader: object too large to be read back on a 32-bit platform");break;default:m("caml_input_value_from_reader: bad object");break}var +n=[],c=p>0?[]:null,i=0;function +l(a){var +k=a.read8u();if(k>=0x40)if(k>=u){var +r=k&0xF,l=k>>4&0x7,b=[r];if(l==0)return b;if(c)c[i++]=b;n.push(b,l);return b}else +return k&b0;else if(k>=0x20){var +f=k&0x1F,b=a.readstr(f);if(c)c[i++]=b;return b}else +switch(k){case +0x00:return a.read8s();case +0x01:return a.read16s();case +0x02:return a.read32s();case +0x03:m("input_value: integer too large");break;case +0x04:var +j=a.read8u();if(o==0)j=i-j;return c[j];case +0x05:var +j=a.read16u();if(o==0)j=i-j;return c[j];case +0x06:var +j=a.read32u();if(o==0)j=i-j;return c[j];case +0x08:var +t=a.read32u(),r=t&dO,l=t>>10,b=[r];if(l==0)return b;if(c)c[i++]=b;n.push(b,l);return b;case +0x13:m("input_value: data block too large");break;case +0x09:var +f=a.read8u(),b=a.readstr(f);if(c)c[i++]=b;return b;case +0x0A:var +f=a.read32u(),b=a.readstr(f);if(c)c[i++]=b;return b;case +0x0C:var +g=new +Array(8);for(var +d=0;d<8;d++)g[7-d]=a.read8u();var +b=aB(g);if(c)c[i++]=b;return b;case +0x0B:var +g=new +Array(8);for(var +d=0;d<8;d++)g[d]=a.read8u();var +b=aB(g);if(c)c[i++]=b;return b;case +0x0E:var +f=a.read8u(),b=new +Array(f+1);b[0]=$;var +g=new +Array(8);if(c)c[i++]=b;for(var +d=1;d<=f;d++){for(var +h=0;h<8;h++)g[7-h]=a.read8u();b[d]=aB(g)}return b;case +0x0D:var +f=a.read8u(),b=new +Array(f+1);b[0]=$;var +g=new +Array(8);if(c)c[i++]=b;for(var +d=1;d<=f;d++){for(var +h=0;h<8;h++)g[h]=a.read8u();b[d]=aB(g)}return b;case +0x07:var +f=a.read32u(),b=new +Array(f+1);b[0]=$;if(c)c[i++]=b;var +g=new +Array(8);for(var +d=1;d<=f;d++){for(var +h=0;h<8;h++)g[7-h]=a.read8u();b[d]=aB(g)}return b;case +0x0F:var +f=a.read32u(),b=new +Array(f+1);b[0]=$;var +g=new +Array(8);for(var +d=1;d<=f;d++){for(var +h=0;h<8;h++)g[h]=a.read8u();b[d]=aB(g)}return b;case +0x10:case +0x11:m("input_value: code pointer");break;case +0x12:case +0x18:case +0x19:var +s,v=e;while((s=a.read8u())!=0)v+=String.fromCharCode(s);var +q=aA[v],p;if(!q)m("input_value: unknown custom block identifier");switch(k){case +0x12:break;case +0x19:if(!q.fixed_length)m("input_value: expected a fixed-size custom block");p=q.fixed_length;break;case +0x18:p=a.read32u();a.read32s();a.read32s();break}var +w=a.i,l=[0],b=q.deserialize(a,l);if(p!=undefined)if(p!=l[0])m("input_value: incorrect length of serialized custom block");if(c)c[i++]=b;return b;default:m("input_value: ill-formed message")}}if(o)if(eG)var +v=d.readuint8array(h),g=new +Uint8Array(r),g=eG(v,g),d=new +ck(g,0);else +m("input_value: compressed object, cannot decompress");var +g=l(d);while(n.length>0){var +q=n.pop(),j=n.pop(),k=j.length;if(k>16;return c}function +hp(a,b,c){var +p=2,q=3,t=5,e=6,i=7,h=8,k=9,o=1,n=2,s=3,u=4,r=5;if(!a.lex_default){a.lex_base=aZ(a[o]);a.lex_backtrk=aZ(a[n]);a.lex_check=aZ(a[r]);a.lex_trans=aZ(a[u]);a.lex_default=aZ(a[s])}var +f,d=b,l=a2(c[p]);if(d>=0){c[i]=c[t]=c[e];c[h]=-1}else +d=-d-1;for(;;){var +g=a.lex_base[d];if(g<0)return-g-1;var +j=a.lex_backtrk[d];if(j>=0){c[i]=c[e];c[h]=j}if(c[e]>=c[q])if(c[k]==0)return-d-1;else +f=aw;else{f=l[c[e]];c[e]++}if(a.lex_check[g+f]==d)d=a.lex_trans[g+f];else +d=a.lex_default[d];if(d<0){c[e]=c[i];if(c[h]==-1)m("lexing: empty token");else +return c[h]}else if(f==aw)c[k]=0}}function +J(a,b){if(a<0)aT();var +a=a+1|0,c=new +Array(a);c[0]=0;for(var +d=1;d>7)a[0]=true;d=e|b&bi}return d}switch(c.read32u()){case +0x8495A6BE:var +e=20,d=c.read32u();break;case +0x8495A6BD:var +e=c.read8u()&b0,f=[false],d=g(f);if(f[0])m("Marshal.data_size: object too large to be read back on this platform");break;case +0x8495A6BF:default:m("Marshal.data_size: bad object");break}return e-hs+d}function +gV(){var +a=new +ArrayBuffer(64),b=new +Uint32Array(a),c=new +Uint8Array(a);return{len:0,w:new +Uint32Array([0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476]),b32:b,b8:c}}var +bl=function(){function +k(a,b){return a+b|0}function +l(a,b,c,d,e,f){b=k(k(b,a),k(d,f));return k(b<>>32-e,c)}function +g(a,b,c,d,e,f,g){return l(b&c|~b&d,a,b,e,f,g)}function +h(a,b,c,d,e,f,g){return l(b&d|c&~d,a,b,e,f,g)}function +i(a,b,c,d,e,f,g){return l(b^c^d,a,b,e,f,g)}function +j(a,b,c,d,e,f,g){return l(c^(b|~d),a,b,e,f,g)}return function(a,b){var +c=a[0],d=a[1],e=a[2],f=a[3];c=g(c,d,e,f,b[0],7,0xD76AA478);f=g(f,c,d,e,b[1],12,0xE8C7B756);e=g(e,f,c,d,b[2],17,0x242070DB);d=g(d,e,f,c,b[3],22,0xC1BDCEEE);c=g(c,d,e,f,b[4],7,0xF57C0FAF);f=g(f,c,d,e,b[5],12,0x4787C62A);e=g(e,f,c,d,b[6],17,0xA8304613);d=g(d,e,f,c,b[7],22,0xFD469501);c=g(c,d,e,f,b[8],7,0x698098D8);f=g(f,c,d,e,b[9],12,0x8B44F7AF);e=g(e,f,c,d,b[10],17,0xFFFF5BB1);d=g(d,e,f,c,b[11],22,0x895CD7BE);c=g(c,d,e,f,b[12],7,0x6B901122);f=g(f,c,d,e,b[13],12,0xFD987193);e=g(e,f,c,d,b[14],17,0xA679438E);d=g(d,e,f,c,b[15],22,0x49B40821);c=h(c,d,e,f,b[1],5,0xF61E2562);f=h(f,c,d,e,b[6],9,0xC040B340);e=h(e,f,c,d,b[11],14,0x265E5A51);d=h(d,e,f,c,b[0],20,0xE9B6C7AA);c=h(c,d,e,f,b[5],5,0xD62F105D);f=h(f,c,d,e,b[10],9,0x02441453);e=h(e,f,c,d,b[15],14,0xD8A1E681);d=h(d,e,f,c,b[4],20,0xE7D3FBC8);c=h(c,d,e,f,b[9],5,0x21E1CDE6);f=h(f,c,d,e,b[14],9,0xC33707D6);e=h(e,f,c,d,b[3],14,0xF4D50D87);d=h(d,e,f,c,b[8],20,0x455A14ED);c=h(c,d,e,f,b[13],5,0xA9E3E905);f=h(f,c,d,e,b[2],9,0xFCEFA3F8);e=h(e,f,c,d,b[7],14,0x676F02D9);d=h(d,e,f,c,b[12],20,0x8D2A4C8A);c=i(c,d,e,f,b[5],4,0xFFFA3942);f=i(f,c,d,e,b[8],11,0x8771F681);e=i(e,f,c,d,b[11],16,0x6D9D6122);d=i(d,e,f,c,b[14],23,0xFDE5380C);c=i(c,d,e,f,b[1],4,0xA4BEEA44);f=i(f,c,d,e,b[4],11,0x4BDECFA9);e=i(e,f,c,d,b[7],16,0xF6BB4B60);d=i(d,e,f,c,b[10],23,0xBEBFBC70);c=i(c,d,e,f,b[13],4,0x289B7EC6);f=i(f,c,d,e,b[0],11,0xEAA127FA);e=i(e,f,c,d,b[3],16,0xD4EF3085);d=i(d,e,f,c,b[6],23,0x04881D05);c=i(c,d,e,f,b[9],4,0xD9D4D039);f=i(f,c,d,e,b[12],11,0xE6DB99E5);e=i(e,f,c,d,b[15],16,0x1FA27CF8);d=i(d,e,f,c,b[2],23,0xC4AC5665);c=j(c,d,e,f,b[0],6,0xF4292244);f=j(f,c,d,e,b[7],10,0x432AFF97);e=j(e,f,c,d,b[14],15,0xAB9423A7);d=j(d,e,f,c,b[5],21,0xFC93A039);c=j(c,d,e,f,b[12],6,0x655B59C3);f=j(f,c,d,e,b[3],10,0x8F0CCC92);e=j(e,f,c,d,b[10],15,0xFFEFF47D);d=j(d,e,f,c,b[1],21,0x85845DD1);c=j(c,d,e,f,b[8],6,0x6FA87E4F);f=j(f,c,d,e,b[15],10,0xFE2CE6E0);e=j(e,f,c,d,b[6],15,0xA3014314);d=j(d,e,f,c,b[13],21,0x4E0811A1);c=j(c,d,e,f,b[4],6,0xF7537E82);f=j(f,c,d,e,b[11],10,0xBD3AF235);e=j(e,f,c,d,b[2],15,0x2AD7D2BB);d=j(d,e,f,c,b[9],21,0xEB86D391);a[0]=k(c,a[0]);a[1]=k(d,a[1]);a[2]=k(e,a[2]);a[3]=k(f,a[3])}}();function +gW(a,b,c){var +e=a.len&ab,d=0;a.len+=c;if(e){var +f=64-e;if(c=64){a.b8.set(b.subarray(d,d+64),0);bl(a.w,a.b32);c-=64;d+=64}if(c)a.b8.set(b.subarray(d,d+c),0)}function +gU(a){var +c=a.len&ab;a.b8[c]=u;c++;if(c>56){for(var +b=c;b<64;b++)a.b8[b]=0;bl(a.w,a.b32);for(var +b=0;b<56;b++)a.b8[b]=0}else +for(var +b=c;b<56;b++)a.b8[b]=0;a.b32[14]=a.len<<3;a.b32[15]=a.len>>29&0x1FFFFFFF;bl(a.w,a.b32);var +e=new +Uint8Array(16);for(var +d=0;d<4;d++)for(var +b=0;b<4;b++)e[d*4+b]=a.w[d]>>8*b&dO;return e}function +ht(a,b,c){var +d=gV(),e=a2(a);gW(d,e.subarray(b,b+c),c);return cy(gU(d))}function +hu(a,b,c){return ht(I(a),b,c)}var +U=new +Array();function +aE(a){var +b=U[a];if(!b.opened)j("Cannot flush a closed channel");if(!b.buffer||b.buffer_curr==0)return 0;if(b.output)b.output(a1(b.buffer,0,b.buffer_curr));else +b.file.write(b.offset,b.buffer,0,b.buffer_curr);b.offset+=b.buffer_curr;b.buffer_curr=0;return 0}function +hL(a,b){if(b.name)try{var +d=require(b_),c=d.openSync(b.name,"rs");return new +D(c,b)}catch(f){}return new +D(a,b)}var +bx=new +Array(3);function +aS(a,b){t.call(this,v(0));this.log=function(a){return 0};if(a==1&&typeof +console.log=="function")this.log=console.log;else if(a==2&&typeof +console.error=="function")this.log=console.error;else if(typeof +console.log=="function")this.log=console.log;this.flags=b}aS.prototype.length=function(){return 0};aS.prototype.write=function(a,b,c,d){if(this.log){if(d>0&&c>=0&&c+d<=b.length&&b[c+d-1]==10)d--;var +e=v(d);S(cm(b),c,e,0,d);this.log(e.toUtf16());return 0}j(this.fd+dN)};aS.prototype.read=function(a,b,c,d){j(this.fd+": file descriptor is write only")};aS.prototype.close=function(){this.log=undefined};function +by(a,b){if(b==undefined)b=bx.length;bx[b]=a;return b|0}function +hU(a,b,c){var +d={};while(b){switch(b[1]){case +0:d.rdonly=1;break;case +1:d.wronly=1;break;case +2:d.append=1;break;case +3:d.create=1;break;case +4:d.truncate=1;break;case +5:d.excl=1;break;case +6:d.binary=1;break;case +7:d.text=1;break;case +8:d.nonblock=1;break}b=b[2]}if(d.rdonly&&d.wronly)j(T(a)+cb);if(d.text&&d.binary)j(T(a)+b6);var +e=e0(a),f=e.device.open(e.rest,d);return by(f,undefined)}(function(){function +a(a,b){return a3()?hL(a,b):new +aS(a,b)}by(a(0,{rdonly:1,altname:"/dev/stdin",isCharacterDevice:true}),0);by(a(1,{buffered:2,wronly:1,isCharacterDevice:true}),1);by(a(2,{buffered:2,wronly:1,isCharacterDevice:true}),2)}());function +hw(a){var +b=bx[a];if(b.flags.wronly)j(ej+a+" is writeonly");var +d=null,c={file:b,offset:b.flags.append?b.length():0,fd:a,opened:true,out:false,buffer_curr:0,buffer_max:0,buffer:new +Uint8Array(em),refill:d};U[c.fd]=c;return c.fd}function +eL(a){var +b=bx[a];if(b.flags.rdonly)j(ej+a+" is readonly");var +d=b.flags.buffered!==undefined?b.flags.buffered:1,c={file:b,offset:b.flags.append?b.length():0,fd:a,opened:true,out:true,buffer_curr:0,buffer:new +Uint8Array(em),buffered:d};U[c.fd]=c;return c.fd}function +hx(){var +b=0;for(var +a=0;ae.buffer.length){var +g=new +Uint8Array(e.buffer_curr+b.length);g.set(e.buffer);e.buffer=g}switch(e.buffered){case +0:e.buffer.set(b,e.buffer_curr);e.buffer_curr+=b.length;aE(a);break;case +1:e.buffer.set(b,e.buffer_curr);e.buffer_curr+=b.length;if(e.buffer_curr>=e.buffer.length)aE(a);break;case +2:var +f=b.lastIndexOf(10);if(f<0){e.buffer.set(b,e.buffer_curr);e.buffer_curr+=b.length;if(e.buffer_curr>=e.buffer.length)aE(a)}else{e.buffer.set(b.subarray(0,f+1),e.buffer_curr);e.buffer_curr+=f+1;aE(a);e.buffer.set(b.subarray(f+1),e.buffer_curr);e.buffer_curr+=b.length-f-1}break}return 0}function +hy(a,b,c,d){var +b=a2(b);return hA(a,b,c,d)}function +eM(a,b,c,d){return hy(a,I(b),c,d)}function +hz(a,b){var +c=B(String.fromCharCode(b));eM(a,c,0,1);return 0}function +hB(a,b){if(b==0)cv();return a%b}function +eO(a,b){return+(bn(a,b,false)!=0)}function +hD(a,b){a[0]=bf;a[1]=b;return 0}function +eP(a){if(a +instanceof +Array&&a[0]==a[0]>>>0)return a[0];else if(bt(a))return b2;else if(bu(a))return b2;else if(a +instanceof +Function||typeof +a=="function")return 247;else if(a&&a.caml_custom)return cc;else +return aa}function +gZ(a){var +c={};if(a)for(var +b=1;b=0)a=e;else +m("caml_register_global: cannot locate "+d)}}r[a+1]=b;if(c)r[c]=b}function +eS(a,b){eN[T(a)]=b;return 0}function +eU(a,b){if(a===b)return 1;return 0}function +hI(){o(b3)}function +p(a,b){if(b>>>0>=f(a))hI();return a0(a,b)}function +hJ(a,b){return 1-eU(a,b)}function +hK(){return 0x7FFFFFFF/4|0}function +hF(){eQ(r.Not_found)}function +eV(a){var +b=eZ(aY(a));if(b===undefined)hF();return K(b)}function +hM(){if(l.crypto)if(l.crypto.getRandomValues){var +a=l.crypto.getRandomValues(new +Int32Array(4));return[0,a[0],a[1],a[2],a[3]]}else if(l.crypto.randomBytes){var +a=new +Int32Array(l.crypto.randomBytes(16).buffer);return[0,a[0],a[1],a[2],a[3]]}var +b=new +Date().getTime(),c=b^0xffffffff*Math.random();return[0,c]}function +aF(a){var +b=1;while(a&&a.joo_tramp){a=a.joo_tramp.apply(null,a.joo_args);b++}return a}function +h(a,b){return{joo_tramp:a,joo_args:b}}function +W(a){{if(a +instanceof +Array)return a;var +b;if(l.RangeError&&a +instanceof +l.RangeError&&a.message&&a.message.match(/maximum call stack/i))b=r.Stack_overflow;else if(l.InternalError&&a +instanceof +l.InternalError&&a.message&&a.message.match(/too much recursion/i))b=r.Stack_overflow;else if(a +instanceof +l.Error&&ae(bZ))b=[0,ae(bZ),a];else +b=[0,r.Failure,K(String(a))];if(a +instanceof +l.Error)b.js_error=a;return b}}function +hl(a){switch(a[2]){case-8:case-11:case-12:return 1;default:return 0}}function +g7(a){var +b=e;if(a[0]==0){b+=a[1][1];if(a.length==3&&a[2][0]==0&&hl(a[1]))var +g=a[2],h=1;else +var +h=2,g=a;b+="(";for(var +f=h;fh)b+=", ";var +d=g[f];if(typeof +d=="number")b+=d.toString();else if(d +instanceof +R)b+=aO+d.toString()+aO;else if(typeof +d=="string")b+=aO+d.toString()+aO;else +b+="_"}b+=")"}else if(a[0]==c)b+=a[1];return b}function +eH(a){if(a +instanceof +Array&&(a[0]==0||a[0]==c)){var +d=ae("Printexc.handle_uncaught_exception");if(d)bm(d,[a,false]);else{var +e=g7(a),b=ae(en);if(b)bm(b,[0]);console.error("Fatal error: exception "+e);if(a.js_error)throw a.js_error}}else +throw a}function +hH(){var +c=l.process;if(c&&c.on)c.on("uncaughtException",function(a,b){eH(a);c.exit(2)});else if(l.addEventListener)l.addEventListener("error",function(a){if(a.error)eH(a.error)})}hH();function +i(a,b){return(a.l>=0?a.l:a.l=a.length)==1?a(b):az(a,[b])}function +q(a,b,c){return(a.l>=0?a.l:a.l=a.length)==2?a(b,c):az(a,[b,c])}function +gT(a,b,c,d){return(a.l>=0?a.l:a.l=a.length)==3?a(b,c,d):az(a,[b,c,d])}var +hS=undefined;g8();var +cD=[c,ef,-2],cC=[c,cj,-3],cB=[c,dY,-4],z=[c,dZ,-7],x=[c,d3,-11],cQ=[0,e,1,0,0],da=ei,dn=[0,1,0],bb=[0,0,0],dz="<",dA=">",dB="@",dC=""",dD="&",dE="'";A(11,[c,eb,-12],eb);A(10,x,d3);A(9,[c,d7,-10],d7);A(8,[c,dR,-9],dR);A(7,[c,ek,-8],ek);A(6,z,dZ);A(5,[c,d$,-6],d$);A(4,[c,er,-5],er);A(3,cB,dY);A(2,cC,cj);A(1,cD,ef);A(0,[c,eq,-1],eq);function +an(a){throw k([0,cC,a],1)}function +w(a){throw k([0,cB,a],1)}function +bz(a,b){return ho(a,b)?a:b}function +aH(a,b){var +c=f(a),e=f(b),d=v(c+e|0);al(a,0,d,0,c);al(b,0,d,c,e);return am(d)}function +a4(a,b){if(!a)return b;var +c=a[1];return[0,c,a4(a[2],b)]}hw(0);var +a5=eL(1);eL(2);function +cE(a,b){eM(a,b,0,f(b));return}function +cF(a){var +b=hx(0);for(;;){if(!b)return 0;var +d=b[2],e=b[1];try{aE(e)}catch(f){var +c=W(f);if(c[1]!==cD)throw k(c,0)}var +b=d}}eS(en,cF);var +bA=hK(0),aI=(4*bA|0)-1|0,e1=[c,"CamlinternalLazy.Undefined",bp(0)];function +cG(d,b,c){var +a=i(b,0);if(!a)return 0;var +e=a[2];return[0,i(d,a[1]),function(a){return cG(d,e,a)}]}function +cH(d,b,c){var +e=b;for(;;){var +a=i(e,0);if(!a)return 0;var +f=a[2],g=a[1];if(i(d,g))return[0,g,function(a){return cH(d,f,a)}];var +e=f}}function +bB(a){return 25>>0?a:a+32|0}var +e4="hd";function +ao(a){var +c=0,b=a;for(;;){if(!b)return c;var +c=c+1|0,b=b[2]}}function +cI(a){return a?a[1]:an(e4)}function +E(a,b){var +c=a,d=b;for(;;){if(!c)return d;var +e=[0,c[1],d],c=c[2],d=e}}function +af(a){return E(a,0)}function +C(a,b){if(!b)return 0;var +c=b[2],d=i(a,b[1]);return[0,d,C(a,c)]}function +cJ(a,b,c){if(!c)return 0;var +d=c[2],e=q(b,a,c[1]);return[0,e,cJ(a+1|0,b,d)]}function +a6(a,b){return cJ(0,a,b)}function +cK(a,b){var +c=b;for(;;){if(!c)return 0;var +d=c[2];i(a,c[1]);var +c=d}}function +ap(a,b,c){var +e=b,d=c;for(;;){if(!d)return e;var +f=d[2],e=q(a,e,d[1]),d=f}}function +bC(f){var +g=0;return function(a){var +c=g,b=a;for(;;){if(!b)return af(c);var +d=b[2],e=b[1];if(i(f,e))var +c=[0,e,c],b=d;else +var +b=d}}}function +a7(c,b){function +j(a,b){if(2===a){if(b){var +j=b[2];if(j){var +k=j[1],l=b[1],y=j[2],z=0>1,t=r(s,b),A=t[1],u=r(a-s|0,t[2]),i=A,h=u[1],g=0,B=u[2];for(;;){if(i){if(h){var +o=h[1],p=i[1],w=h[2],x=i[2];if(0>1,t=j(s,b),A=t[1],u=j(a-s|0,t[2]),i=A,h=u[1],g=0,B=u[2];for(;;){if(i){if(h){var +p=h[1],r=i[1],w=h[2],x=i[2];if(0=b){var +d=v(c);S(a,b,d,0,c);return d}return w(e5)}function +cN(a,b,c){return am(cM(a,b,c))}var +e7="String.concat",e8=e,e9="String.contains_from / Bytes.contains_from";function +bD(a,b){var +c=v(a);g6(c,0,a,b);return am(c)}function +a8(a,b,c){return am(cM(I(a),b,c))}function +a9(a,b){if(!b)return e8;var +j=f(a);a:{b:{var +e=0,d=b,q=0;for(;;){if(!d)break;var +k=d[1];if(!d[2])break b;var +l=(f(k)+j|0)+e|0,n=d[2],o=e<=l?l:w(e7),e=o,d=n}var +m=e;break a}var +m=f(k)+e|0}var +i=v(m),h=q,g=b;for(;;){if(g){var +c=g[1];if(g[2]){var +p=g[2];al(c,0,i,h,f(c));al(a,0,i,h+f(c)|0,j);var +h=(h+f(c)|0)+j|0,g=p;continue}al(c,0,i,h,f(c))}return am(i)}}function +bE(a,b){var +d=f(a),h=0;if(d<0)return w(e9);try{var +c=h;for(;;){if(d<=c)throw k(z,1);if(a0(a,c)===b){var +g=1;return g}var +c=c+1|0}}catch(f){var +e=W(f);if(e===z)return 0;throw k(e,0)}}function +cO(a){var +d=I(a),c=ad(d);if(0===c)var +g=d;else{var +e=v(c),f=c-1|0,h=0;if(f>=0){var +b=h;for(;;){eD(e,b,bB(g2(d,b)));var +i=b+1|0;if(f===b)break;var +b=i}}var +g=e}return am(g)}function +bF(a,b){var +d=[0,0],e=[0,f(b)],g=f(b)-1|0;if(g>=0){var +c=g;for(;;){if(a0(b,c)===a){var +i=d[1];d[1]=[0,a8(b,c+1|0,(e[1]-c|0)-1|0),i];e[1]=c}var +j=c-1|0;if(0===c)break;var +c=j}}var +h=d[1];return[0,a8(b,0,e[1]),h]}function +cP(a,b){var +d=b.length-1;if(0===d)return[0];var +e=J(d,i(a,b[1])),f=d-1|0,g=1;if(f>=1){var +c=g;for(;;){e[1+c]=i(a,b[1+c]);var +h=c+1|0;if(f===c)break;var +c=h}}return e}var +bG=[c,"Stdlib.Array.Bottom",bp(0)];function +cR(a,b,c){return cN(a[2],b,c-b|0)}var +e6="Bytes.blit",fh=[0,dJ,94,2],fi=[0,dJ,93,2],fj="Buffer.add: cannot grow buffer";function +cW(a){var +b=1<=a?a:1,c=aI=(e+b|0))break;c[1]=2*c[1]|0}if(aI=0&&(ad(f)-d|0)>=0){S(g,0,f,0,d);break a}w(e6)}a[1]=f;a[3]=c[1];if((a[2]+b|0)>a[3])throw k([0,x,fi],1);if((e+b|0)<=a[3])return;throw k([0,x,fh],1)}function +bI(a,b){var +c=f(b),d=a[2]+c|0;if(a[3]=0){var +d=v;for(;;){var +h=d%55|0,o=hB(d,j),y=g(m,o)[1+o],l=aH(k[1],e+y);k[1]=hu(l,0,f(l));var +i=k[1],r=p(i,3)<<24,s=p(i,2)<<16,t=p(i,1)<<8,u=((p(i,0)+t|0)+s|0)+r|0,z=(g(c[1],h)[1+h]^u)&ec;g(c[1],h)[1+h]=z;var +A=d+1|0;if(n===d)break;var +d=A}}c[2]=0;return c}];function +bJ(a,b){return 4<=a.length-1?g9(10,100,a[3],b)&(a[2].length-1-1|0):w(fo)}var +c3=[c,fq,bp(0)],bK=[0,c3,[0]],fn=bE(c2,82),fp=eP(bK)===c?bK:bK[1];eS(bZ,fp);(function(a){throw a});function +c4(a,b){var +c=a?a[1]:10;return b.toString(c)}l["Number"];var +b=l,ft=b["Promise"];function +bL(a){return ft.resolve(a)}function +bM(a){return{fut:bL(a)}}function +c5(a,b){return{fut:a[cg].then(aD(1,function(a){return i(b,a)[cg]}))}}function +c6(c,b){return c5(b,function(a){return bM(i(c,a))})}function +c7(a,b){return c6(b,a)}b["Event"];var +fu=b["ArrayBuffer"],fv=b["DataView"];b["Blob"];b["File"];b["JSON"];b["encodeURI"];b["decodeURI"];b["encodeURIComponent"];b["decodeURIComponent"];b["URL"];b["URLSearchParams"];var +bQ=b["document"],fs=bQ===null?1:0,fr=undefined,fC=fs||(bQ===fr?1:0);if(!fC)bQ["documentElement"];b[et];b[et];b["navigator"];b["performance"];b["window"];b["isSecureContext"];function +c_(a){return a?a[2]?[2,a]:a[1]:0}function +aJ(a){return a?0:1}function +c$(a){return ap(function(a,b){return E(b,a)},0,a)}function +aK(f,b,c,d){if(typeof +d==="number")return 0===d?f?[0,[0,c,[0,da,b]],0]:[0,[0,c,b],0]:0;switch(d[0]){case +0:var +h=d[1],i=aK(f,b,c,d[2]);return E(aK(f,b,aJ(c),h),i);case +1:var +a=d[2],g=[0,cO(d[1]),b];return a?c$(a6(function(a,b){return aK(f,[0,e+a,g],c,b)},a)):[0,[0,c,g],0];case +2:return c$(C(function(a){return aK(f,b,c,a)},d[1]));default:return[0,[0,c,[0,da,b]],0]}}bD(0,95);function +db(a,b){var +c=aX(f(a),f(b));return 0===c?cx(a,b):c}function +Y(a,b){if(a===b)return 0;var +g=aX(a[5],b[5]);if(0!==g)return g;var +d=db(a[1],b[1]);if(0!==d)return d;var +c=cx(a[7][1],b[7][1]);if(0!==c)return c;var +e=y(a[4],b[4]);if(0!==e)return e;var +f=db(a[6],b[6]);return 0===f?cx(a[3],b[3]):f}function +ba(a,b){var +s=a[1],c=a[2],i=0;for(;;){var +r=c[1];a:b:{var +e=i,k=r,t=r+c[2]|0;for(;;){if(f(b)<=e)break b;if(t<=k)break b;var +u=p(s,k);if(p(b,e)!==u)break;var +e=e+1|0,k=k+1|0}break a}var +h=e-i|0;if((i+h|0)===f(b))var +j=[0,[0,c[1]+h|0,c[2]-h|0,c[3],c[4],c[5]]];else if(h===c[2]){var +m=i+h|0;if(f(b)<=m)var +j=[0,c];else{var +q=c[5];a:{var +v=p(b,m);if(q){var +o=q[1];b:{var +d=0;for(;;){if(o.length-1<=d)break b;var +n=g(o,d)[1+d];if(v===p(s,n[1]-1|0))break;var +d=d+1|0}var +l=[0,n];break a}var +l=0}else +var +l=0}if(l){var +c=l[1],i=m+1|0;continue}var +j=0}}else +var +j=0;return j?[0,[0,a[1],j[1]]]:0}}function +bR(h,b,c,d){function +a(a){var +i=b[2];if(1<=i[2]){var +r=32===p(b[1],i[1])?1:0,l=h+r|0;if(1=0){var +g=o;for(;;){var +e=n[1+g];if(0>e[2])throw k([0,x,fG],1);bR(h,[0,b[1],[0,e[1]-1|0,e[2]+1|0,e[3],e[4],e[5]]],c,d);var +q=g+1|0;if(j===g)break;var +g=q}}return 0}if(0===h)return a(0);if(1===h&&eU(c,ei)){var +e=ba(b,c);return e?i(d,e[1]):0}a(0);var +f=ba(b,c);return f?i(d,f[1]):0}function +cV(a,b,c){var +d=b,e=c;for(;;){if(!d)return e;var +f=d[4],g=d[3],h=d[2],i=gT(a,h,g,cV(a,d[1],e)),d=f,e=i}}var +fI=[c,fH,bp(0)];function +Z(a){throw k(fI,1)}function +as(a){throw k([0,x,fJ],1)}function +O(a,b,c,d,e,f){var +j=i(d,c),g=[1,e,0];return a<50?av(a+1|0,b,c,d,g,f,j):h(av,[0,b,c,d,g,f,j])}function +av(a,b,c,d,e,f,g){var +i=[0,e,0];return a<50?be(a+1|0,b,c,d,i,f,g):h(be,[0,b,c,d,i,f,g])}function +be(a,b,c,d,e,f,g){if(typeof +g==="number")switch(g){case +1:case +6:break;default:var +p=c_(e);return a<50?au(a+1|0,b,c,d,p,f,g):h(au,[0,b,c,d,p,f,g])}else if(0===g[0]){var +m=[0,[0,b,f,e],g[1]],j=i(d,c);if(typeof +j==="number")switch(j){case +1:case +6:break;default:var +q=0;return a<50?bd(a+1|0,m,c,d,q,j):h(bd,[0,m,c,d,q,j])}else if(0===j[0]){a:{var +t=m,s=j[1],r=2;for(;;){var +u=[0,t,r,s],k=i(d,c);if(typeof +k==="number")break;if(0!==k[0])break a;var +t=u,s=k[1],r=3}switch(k){case +1:case +6:break;default:var +l=u,v=0;for(;;){var +w=l[2],n=l[1],o=[0,l[3],v];if(2===w)return a<50?bd(a+1|0,n,c,d,o,k):h(bd,[0,n,c,d,o,k]);if(3!==w)return as(0);var +l=n,v=o}}}return Z(0)}return Z(0)}return Z(0)}function +bd(a,b,c,d,e,f){var +g=b[1],j=g[2],k=g[1],i=ap(function(a,b){return[1,b,[0,a,0]]},[1,b[2],g[3]],e);return a<50?au(a+1|0,k,c,d,i,j,f):h(au,[0,k,c,d,i,j,f])}function +au(a,b,c,d,e,f,g){if(typeof +g==="number")switch(g){case +0:var +k=[0,b,f,e],l=5,o=i(d,c);if(typeof +o==="number")switch(o){case +1:return a<50?ai(a+1|0,k,c,d,l):h(ai,[0,k,c,d,l]);case +6:return a<50?M(a+1|0,k,c,d,l):h(M,[0,k,c,d,l]);default:return a<50?L(a+1|0,k,c,d,l,o):h(L,[0,k,c,d,l,o])}if(0===o[0]){var +p=o[1];return a<50?O(a+1|0,k,c,d,p,l):h(O,[0,k,c,d,p,l])}var +q=o[1];return a<50?N(a+1|0,k,c,d,q,l):h(N,[0,k,c,d,q,l]);case +1:case +6:break;default:var +j=b,n=[0,e,0],m=f;for(;;)switch(m){case +0:return a<50?_(a+1|0,j,c,d,n,m,g):h(_,[0,j,c,d,n,m,g]);case +1:return a<50?_(a+1|0,j,c,d,n,m,g):h(_,[0,j,c,d,n,m,g]);case +4:return a<50?_(a+1|0,j,c,d,n,m,g):h(_,[0,j,c,d,n,m,g]);case +5:var +s=[0,j[3],n],r=j[2],j=j[1],n=s,m=r;break;case +6:return a<50?_(a+1|0,j,c,d,n,m,g):h(_,[0,j,c,d,n,m,g]);default:return as(0)}}return as(0)}function +N(a,b,c,d,e,f){var +g=i(d,c),j=[3,e];return a<50?av(a+1|0,b,c,d,j,f,g):h(av,[0,b,c,d,j,f,g])}function +ai(a,b,c,d,e){var +l=b,k=e;for(;;){var +f=[0,l,k],g=1,j=i(d,c);if(typeof +j!=="number"){if(0===j[0]){var +m=j[1];return a<50?O(a+1|0,f,c,d,m,g):h(O,[0,f,c,d,m,g])}var +n=j[1];return a<50?N(a+1|0,f,c,d,n,g):h(N,[0,f,c,d,n,g])}switch(j){case +1:var +l=f,k=g;break;case +3:return Z(0);case +6:return a<50?M(a+1|0,f,c,d,g):h(M,[0,f,c,d,g]);default:return a<50?L(a+1|0,f,c,d,g,j):h(L,[0,f,c,d,g,j])}}}function +M(a,b,c,d,e){var +f=i(d,c),g=0;return a<50?av(a+1|0,b,c,d,g,e,f):h(av,[0,b,c,d,g,e,f])}function +L(a,b,c,d,e,f){var +g=0;return a<50?au(a+1|0,b,c,d,g,e,f):h(au,[0,b,c,d,g,e,f])}function +_(a,b,c,d,e,f,g){var +p=c_(e);if(typeof +g==="number")switch(g){case +5:var +j=[0,b,f,p],k=4,m=i(d,c);if(typeof +m==="number")switch(m){case +1:return a<50?ai(a+1|0,j,c,d,k):h(ai,[0,j,c,d,k]);case +6:return a<50?M(a+1|0,j,c,d,k):h(M,[0,j,c,d,k]);default:return a<50?L(a+1|0,j,c,d,k,m):h(L,[0,j,c,d,k,m])}if(0===m[0]){var +q=m[1];return a<50?O(a+1|0,j,c,d,q,k):h(O,[0,j,c,d,q,k])}var +r=m[1];return a<50?N(a+1|0,j,c,d,r,k):h(N,[0,j,c,d,r,k]);case +0:case +1:case +6:break;default:var +l=b,n=p,o=f;for(;;)switch(o){case +0:if(typeof +g==="number"&&3===g)return n;return Z(0);case +1:return a<50?bc(a+1|0,l,c,d,n,o,g):h(bc,[0,l,c,d,n,o,g]);case +4:var +t=[0,l[3],n],s=l[2],l=l[1],n=t,o=s;break;case +6:return a<50?bc(a+1|0,l,c,d,n,o,g):h(bc,[0,l,c,d,n,o,g]);default:return as(0)}}return as(0)}function +bc(a,b,c,d,e,f,g){if(typeof +g==="number"){var +p=g-2|0;if(2>=p>>>0)switch(p){case +0:var +m=b,n=[0,e,0],o=f;for(;;){if(1===o){var +s=i(d,c),t=m[2],u=m[1];return a<50?be(a+1|0,u,c,d,n,t,s):h(be,[0,u,c,d,n,t,s])}if(6>o)return as(0);var +w=[0,m[3],n],v=m[2],m=m[1],n=w,o=v}break;case +1:break;default:var +j=[0,b,f,e],k=6,l=i(d,c);if(typeof +l==="number")switch(l){case +1:return a<50?ai(a+1|0,j,c,d,k):h(ai,[0,j,c,d,k]);case +3:return Z(0);case +6:return a<50?M(a+1|0,j,c,d,k):h(M,[0,j,c,d,k]);default:return a<50?L(a+1|0,j,c,d,k,l):h(L,[0,j,c,d,k,l])}if(0===l[0]){var +q=l[1];return a<50?O(a+1|0,j,c,d,q,k):h(O,[0,j,c,d,q,k])}var +r=l[1];return a<50?N(a+1|0,j,c,d,r,k):h(N,[0,j,c,d,r,k])}}return Z(0)}function +at(a){for(;;){var +e=0;for(;;){var +b=hp(fP,e,a),d=0<=b?1:0,f=d?a[12]!==fb?1:0:d;if(f){a[11]=a[12];var +c=a[12];a[12]=[0,c[1],c[2],c[3],a[4]+a[6]|0]}if(9>=b>>>0)break;i(a[1],a);var +e=b}switch(b){case +0:break;case +1:return 5;case +2:return 1;case +3:return 2;case +4:return 4;case +5:return 6;case +6:return 0;case +7:return[1,cR(a,a[5]+1|0,a[6])];case +8:return[0,cR(a,a[5],a[6])];default:return 3}}}function +dc(a,b){if(0>b)return 0;if(f(a)>b){var +c=fQ,h=p(a,b);for(;;){if(c){var +g=c[2],d=0===y(c[1],h)?1:0;if(!d){var +c=g;continue}var +e=d}else +var +e=0;if(e)break;return 95===p(a,b)?3:10}}return 1}function +dd(a,e,c){var +o=a?a[1]:0,h=0,i=0;for(;;){if(f(c)<(h+f(e)|0))break;a:{b:{var +g=0,b=0,d=h;for(;;){if(f(e)<=b)break b;var +k=p(c,d);if(p(e,b)===k)var +b=b+1|0,d=d+1|0;else{var +l=bB(p(c,d));if(p(e,b)===l)var +g=g+3|0,b=b+1|0,d=d+1|0;else{var +m=p(c,d);if(bB(p(e,b))!==m)break;var +g=g+10|0,b=b+1|0,d=d+1|0}}}var +j=0;break a}var +j=[0,g]}var +n=j?[0,[0,h,j[1]],i]:i,h=h+1|0,i=n}return ap(function(a,b){var +d=b[1],h=b[2],i=dc(c,d-1|0),j=dc(c,d+f(e)|0)/3|0,k=o<=d?0:10,g=((h+i|0)+j|0)+k|0;if(a&&a[1][2]=g){var +t=g<=f?f+1|0:g+1|0;return[0,a,b,c,t]}if(!c)return w(ff);var +i=c[3],k=c[2],e=c[1],p=a_(e);if(p<=a_(i))return F(F(a,b,e),k,i);if(!e)return w(fe);var +q=e[2],r=e[1],s=F(e[3],k,i);return F(F(a,b,r),q,s)}function +a$(a,b){if(!b)return[0,0,a,0,1];var +c=b[3],d=b[2],e=b[1],f=Y(a,d);if(0===f)return b;if(0<=f){var +g=a$(a,c);return c===g?b:aq(e,d,g)}var +h=a$(a,e);return e===h?b:aq(h,d,c)}function +cS(a){if(!a)return w(fg);var +b=a[1];if(!b)return a[3];var +c=a[3],d=a[2];return aq(cS(b),d,c)}function +bH(a,b){if(!b)return 0;var +c=b[3],f=b[2],d=b[1],h=Y(a,f);if(0!==h){if(0<=h){var +i=bH(a,c);return c===i?b:aq(d,f,i)}var +j=bH(a,d);return d===j?b:aq(j,f,c)}if(!d)return c;if(!c)return d;var +e=c,l=cS(c);for(;;){if(!e)throw k(z,1);var +g=e[1];if(!g)return aq(d,e[2],l);var +e=g}}function +cT(a,b){var +c=a,d=b;for(;;){if(!c)return d;var +e=[0,c[2],c[3],d],c=c[1],d=e}}function +cU(a,b){if(!a)return 0;var +c=a[1],d=cT(a[2],a[3]);return[0,c,function(a){return cU(d,a)}]}function +dk(a,b){var +am=b[1],P=ap(function(a,b){var +c=a[3],d=a[2],e=a[1],g=dd([0,e],b,am);if(!g)return[0,e,d,(c+f(b)|0)+50|0];var +h=g[1];return[0,h[1]+f(b)|0,d+h[2]|0,c]},fR,a[1]),Y=a[2],G=b[4];a:{var +ai=P[2]+P[3]|0;if(typeof +G!=="number"&&1!==G[0]){var +H=[0,G[1]];break a}var +H=0}if(Y){var +X=Y[1];if(H){var +V=df(H[1]);a:{if(X&&V){var +n=C(function(f){return C(function(a){var +m=ao(f),d=1+m|0,i=J(d,[0]),c=d-1|0,n=1+ao(a)|0,k=0;if(c>=0){var +b=k;for(;;){i[1+b]=J(n,-1);var +l=b+1|0;if(c===b)break;var +b=l}}function +h(a,b,c,d,e,f){var +h=g(g(i,c)[1+c],d)[1+d];if(0<=h)return h;var +k=j(a,b,c,d,e,f);g(g(i,c)[1+c],d)[1+d]=k;return k}function +j(a,b,c,d,e,f){if(!e)return f?0:0;var +g=e[1];a:{b:{c:{d:{e:{if(typeof +g==="number")switch(g){case +0:if(!e[2]){if(!f)break c;var +s=f[1];if(typeof +s==="number"&&2>s&&!f[2]&&a===b)return 0}break;case +1:if(!e[2]&&a===b)return 0;break;case +2:if(!f)break e;var +t=f[1];if(typeof +t==="number"&&2===t){var +E=f[2],F=e[2],G=aJ(b);return h(aJ(a),G,c+1|0,d+1|0,F,E)}break}if(f){var +u=f[2],v=e[2];if(g4(g,f[1])&&a===b)return h(a,b,c+1|0,d+1|0,v,u);if(typeof +g==="number"){if(2===g)break e}else +f:switch(g[0]){case +0:var +i=f[1],y=e[2],z=g[1];if(typeof +i==="number")switch(i){case +2:break f;case +3:break d}else if(0===i[0]){var +q=f[2],A=i[1];if(a!==b)break a;var +r=dd(0,z,A);if(!r)return 10+h(a,b,c,d+1|0,e,q)|0;var +B=r[1][2];return(B/3|0)+h(a,b,c+1|0,d+1|0,y,q)|0}break a;case +1:var +j=f[1],C=e[2];if(typeof +j==="number")switch(j){case +2:break f;case +3:break d}else if(1===j[0])return 1+h(a,b,c+1|0,d+1|0,C,f[2])|0;break b;default:var +k=f[1],D=e[2];if(typeof +k==="number")switch(k){case +2:break f;case +3:break d}else if(2===k[0])return 1+h(a,b,c+1|0,d+1|0,D,f[2])|0;break a}var +l=f[1];if(typeof +l==="number"&&2===l){var +w=f[2];return 1+h(a,aJ(b),c,d+1|0,e,w)|0}}}var +m=e[1];if(typeof +m!=="number")break c;if(2===m){var +x=e[2];return 1+h(aJ(a),b,c+1|0,d,x,f)|0}}if(f){var +n=f[1];if(typeof +n==="number"&&3<=n)return h(a,b,c,d+1|0,e,f[2])}var +o=e[1];if(typeof +o==="number"&&3===o)return h(a,b,c+1|0,d,e[2],f)}if(!f)return ce}if(typeof +e[1]!=="number")return 1+h(a,b,c+1|0,d,e[2],f)|0}var +p=f[1];if(typeof +p==="number")return ce;switch(p[0]){case +0:return 10+h(a,b,c,d+1|0,e,f[2])|0;case +1:return 1+h(a,b,c,d+1|0,e,f[2])|0;default:return h(a,b,c,d+1|0,e,f[2])}}var +e=0;return j(e,e,0,0,f,a)},V)},X);if(!n){var +I=0;break a}var +s=J(ao(cI(n)),0);if(n){var +w=0,v=n,Z=n[2],_=n[1];for(;;){if(!v)break;var +w=w+1|0,v=v[2]}var +K=J(w,_),z=1,p=Z;for(;;){if(!p)break;var +$=p[2];K[1+z]=p[1];var +z=z+1|0,p=$}var +Q=K}else +var +Q=[0];var +d=cP(function(a){return a7(y,a6(function(a,b){return[0,b,a]},a))},Q),L=function(a,b){var +c=((b+b|0)+b|0)+1|0,e=[0,c];if((c+2|0)y(g(d,c)[1+c],n))return c+1|0}if(c=0){var +l=N;for(;;){var +F=g(d,l)[1+l];try{var +j=l;for(;;){var +o=L(r,j);if(0>=y(g(d,o)[1+o],F))break;var +ab=g(d,o)[1+o];g(d,j)[1+j]=ab;var +j=o}g(d,j)[1+j]=F}catch(f){var +A=W(f);if(A[1]!==bG)throw k(A,0);var +M=A[2];g(d,M)[1+M]=F}var +ah=l-1|0;if(0===l)break;var +l=ah}}var +O=r-1|0;if(O>=2){var +i=O;for(;;){var +E=g(d,i)[1+i];d[1+i]=g(d,0)[1];var +af=0;try{var +q=af;for(;;){var +B=L(i,q),ac=g(d,B)[1+B];g(d,q)[1+q]=ac;var +q=B}}catch(f){var +D=W(f);if(D[1]!==bG)throw k(D,0);b:{c:{var +e=D[2];for(;;){var +h=(e-1|0)/3|0;if(e===h)throw k([0,x,fa],1);if(0<=y(g(d,h)[1+h],E))break;var +ad=g(d,h)[1+h];g(d,e)[1+e]=ad;if(0>=h)break c;var +e=h}g(d,e)[1+e]=E;break b}g(d,0)[1]=E}var +ag=i-1|0;if(2===i)break;var +i=ag}}}if(1=0){var +c=R;for(;;){var +U=c+1|0,aj=cI(g(d,c)[1+c])[1],ak=g(t,U)[1+U]+aj|0;g(t,c)[1+c]=ak;var +al=c-1|0;if(0===c)break;var +c=al}}var +m=[0,aa],S=[0,0],T=function(a,b,c){S[1]++;if(ce=a){m[1]=bz(b+(aa*(d.length-1-c|0)|0)|0,m[1]);return 1}if(d.length-1<=c){m[1]=bz(b+(5*a|0)|0,m[1]);return 1}var +j=m[1];if(j<=(b+g(t,c)[1+c]|0))return 1;var +f=g(d,c)[1+c];for(;;){if(!f)return 1;var +h=f[1],e=h[2],k=f[2],l=h[1];if(g(s,e)[1+e])var +i=1;else{g(s,e)[1+e]=1;var +n=T(a-1|0,b+l|0,c+1|0);s[1+e]=0;var +i=n}if(!i)return 0;var +f=k}};T(s.length-1,0,0);var +I=m[1];break a}var +I=0}var +u=[0,I]}else +var +u=fT}else +var +u=0;var +an=u?u[1]:0;return[0,b[1],b[2],b[3],b[4],b[5]+(5*(ai+an|0)|0)|0,b[6],b[7]]}function +dl(a){if(typeof +a==="number")return 0;switch(a[0]){case +0:return a[2].length-1-a[1]|0;case +1:return a[2][2][3];default:return ap(function(a,b){return a+dl(b)|0},0,a[2])}}function +aM(a){if(typeof +a==="number")return 0;if(0!==a[0])return[0,a[1]];var +b=a[1];return[0,g(a[2],b)[1+b]]}function +bS(a){var +b=a[2][4];if(typeof +b==="number")throw k([0,x,fE],1);return[1,g(b[1],0)[1],a]}function +dm(c,b){var +a=aM(c);if(!a)return b;var +h=a[1];function +d(a){var +b=a;for(;;){if(!b)return[0,c,0];var +e=b[2],f=b[1],g=aM(f);if(g)return 0l)break;var +C=[0,B[1+l],n],l=l-1|0,n=C}var +H=dm(s,n),m=bC(function(a){return eO(0,a)})(H),z=m?m[2]?[2,w,m]:m[1]:0}var +a=z;break;default:if(i(d,a[1]))return a;var +A=function(a,b){if(!b)return 0;var +e=b[2],c=b[1],f=bT(d,c);if(c!==f)return dm(f,A(a+1|0,e));if(0>>25|0)&31)|0)&ec,o=a[2];g(a[1],o)[1+o]=n;var +q=n}else +var +q=0;var +c=[0,0,J(d,0),q,d];cK(function(a){try{var +G=bJ(c,a),j=g(c[2],G)[1+G];if(!j)throw k(z,1);var +l=j[3],Z=j[2];if(0===y(a,j[1]))var +o=Z;else{if(!l)throw k(z,1);var +m=l[3],_=l[2];if(0===y(a,l[1]))var +o=_;else{if(!m)throw k(z,1);var +$=m[2],aa=m[3];if(0===y(a,m[1]))var +o=$;else{var +i=aa;for(;;){if(!i)throw k(z,1);var +X=i[2],Y=i[3];if(0===y(a,i[1]))break;var +i=Y}var +o=X}}}var +M=o}catch(f){var +L=W(f);if(L!==z)throw k(L,0);var +M=0}var +N=M+1|0,n=bJ(c,a),H=g(c[2],n)[1+n];a:{b:{var +d=H;for(;;){if(!d)break;var +ab=d[3];if(0===y(d[1],a))break b;var +d=ab}var +u=1;break a}d[1]=a;d[2]=N;var +u=0}if(u){g(c[2],n)[1+n]=[0,a,N,H];c[1]=c[1]+1|0;var +I=c[2].length-1<<1=0){var +h=S;for(;;){var +b=g(r,h)[1+h];for(;;){if(!b)break;var +w=b[1],Q=b[2],R=b[3],q=t?b:[0,w,Q,0],e=bJ(c,w),x=g(p,e)[1+e];if(x)x[3]=q;else +g(s,e)[1+e]=q;g(p,e)[1+e]=q;var +b=R}var +V=h+1|0;if(A===h)break;var +h=V}}if(t){var +B=v-1|0,T=0;if(B>=0){var +f=T;for(;;){var +D=g(p,f)[1+f];if(D)D[3]=0;var +U=f+1|0;if(B===f)break;var +f=U}}var +C=0}else +var +C=t;return C}var +K=I}else +var +K=u;return K},G);var +r=c[2];function +s(a,b,c){var +d=a,e=b;for(;;){if(e){var +f=e[3];return[0,[0,e[1],e[2]],function(a){return s(d,f,a)}]}if(d===r.length-1)return 0;var +h=g(r,d)[1+d],d=d+1|0,e=h}}var +v=0,w=0;function +A(a){return s(w,v,a)}function +B(a){var +b=a[1];return[0,b[2],a[2],b[1]]}function +D(a){return cG(B,A,a)}function +F(a){return 0=0){var +ar=fz;for(;;){var +bO=bY.charCodeAt(ar);if(cc=g>>>0)switch(g){case +0:return a<50?e(a+1|0,dz,b,d):h(e,[0,dz,b,d]);case +2:return a<50?e(a+1|0,dA,b,d):h(e,[0,dA,b,d]);case +4:return a<50?e(a+1|0,dB,b,d):h(e,[0,dB,b,d])}}else if(34<=f)switch(f-34|0){case +0:return a<50?e(a+1|0,dC,b,d):h(e,[0,dC,b,d]);case +4:return a<50?e(a+1|0,dD,b,d):h(e,[0,dD,b,d]);case +5:return a<50?e(a+1|0,dE,b,d):h(e,[0,dE,b,d])}var +d=d+1|0}},e=function(a,b,c,d){l(c,d);bI(g,b);var +e=d+1|0;return a<50?j(a+1|0,e,e):h(j,[0,e,e])};return function(a,b){return aF(j(0,a,b))}(0,0);default:return cK(d,a[1])}};let +d=P;P(ad);B[t]={html:aY(cX(O)),url:aY(aq)};var +t=t+1|0,q=_}})[cg].then(aD(1,function(a){return a}));return 0});cF(0);return}(globalThis)); diff --git a/assets/js/zzzz-search-data.json b/assets/js/zzzz-search-data.json new file mode 100644 index 0000000..2ff3bd2 --- /dev/null +++ b/assets/js/zzzz-search-data.json @@ -0,0 +1,82 @@ +--- +layout: null +permalink: /assets/js/search-data.json +# This is mostly verbatim from the just-the-docs github repository. +# We only add odoc pages to the set of pages that appear in the search. +--- +{ +{%- assign i = 0 -%} +{%- assign pages_array = "" | split: "" -%} +{%- assign pages_array = pages_array | push: site.html_pages -%} +{%- if site.just_the_docs.collections -%} + {%- for collection_entry in site.just_the_docs.collections -%} + {%- assign collection_key = collection_entry[0] -%} + {%- assign collection_value = collection_entry[1] -%} + {%- assign collection = site[collection_key] -%} + {%- if collection_value.search_exclude != true -%} + {%- assign pages_array = pages_array | push: collection -%} + {%- endif -%} + {%- endfor -%} +{%- endif -%} +{%- for page in site.pages -%} + {%- if page.layout == "odoc" -%} + {%- assign pages_array = pages_array | push: page -%} + {%- endif -%} +{%- endfor -%} +{%- for pages in pages_array -%} + {%- for page in pages -%} + {%- if page.title and page.search_exclude != true -%} + {%- assign page_content = page.content -%} + {%- assign heading_level = site.search.heading_level | default: 2 -%} + {%- for j in (2..heading_level) -%} + {%- assign tag = '' -%} + {%- assign title = titleAndContent[0] | replace_first: '>', '

' | split: '

' -%} + {%- assign title = title[1] | strip_html -%} + {%- assign content = titleAndContent[1] -%} + {%- assign url = page.url -%} + {%- if title == page.title and parts[0] == '' -%} + {%- assign title_found = true -%} + {%- else -%} + {%- assign id = titleAndContent[0] -%} + {%- assign id = id | split: 'id="' -%} + {%- if id.size == 2 -%} + {%- assign id = id[1] -%} + {%- assign id = id | split: '"' -%} + {%- assign id = id[0] -%} + {%- capture url -%}{{ url | append: '#' | append: id }}{%- endcapture -%} + {%- endif -%} + {%- endif -%} + {%- unless i == 0 -%},{%- endunless -%} + "{{ i }}": { + "doc": {{ page.title | jsonify }}, + "title": {{ title | jsonify }}, + "content": {{ content | replace: '