mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
163 lines
4.6 KiB
OCaml
163 lines
4.6 KiB
OCaml
(* This file is free software, part of containers. See file "license" for more details. *)
|
|
|
|
(** Hash Tries
|
|
|
|
Trie indexed by the hash of the keys, where the branching factor is fixed.
|
|
The goal is to have a quite efficient functional structure with fast
|
|
update and access {b if} the hash function is good.
|
|
The trie is not binary, to improve cache locality and decrease depth.
|
|
|
|
Preliminary benchmarks (see the "tbl" section of benchmarks) tend to show
|
|
that this type is quite efficient for small data sets.
|
|
|
|
{b status: unstable}
|
|
|
|
@since 0.13
|
|
*)
|
|
|
|
type 'a iter = ('a -> unit) -> unit
|
|
type 'a gen = unit -> 'a option
|
|
type 'a printer = Format.formatter -> 'a -> unit
|
|
type 'a ktree = unit -> [`Nil | `Node of 'a * 'a ktree list]
|
|
|
|
(** {2 Transient Identifiers} *)
|
|
module Transient : sig
|
|
type t
|
|
(** Identifiers for transient modifications. A transient modification
|
|
is uniquely identified by a [Transient.t]. Once [Transient.freeze r]
|
|
is called, [r] cannot be used to modify the structure again. *)
|
|
|
|
val create : unit -> t
|
|
(** Create a new, active ID. *)
|
|
|
|
val equal : t -> t -> bool
|
|
(** Equality between IDs. *)
|
|
|
|
val frozen : t -> bool
|
|
(** [frozen i] returns [true] if [freeze i] was called before. In this case,
|
|
the ID cannot be used for modifications again. *)
|
|
|
|
val active : t -> bool
|
|
(** [active i] is [not (frozen i)]. *)
|
|
|
|
val freeze : t -> unit
|
|
(** [freeze i] makes [i] unusable for new modifications. The values
|
|
created with [i] will now be immutable. *)
|
|
|
|
val with_ : (t -> 'a) -> 'a
|
|
(** [with_ f] creates a transient ID [i], calls [f i],
|
|
freezes the ID [i] and returns the result of [f i]. *)
|
|
|
|
exception Frozen
|
|
(** Raised when a frozen ID is used. *)
|
|
end
|
|
|
|
(** {2 Signature} *)
|
|
module type S = sig
|
|
type key
|
|
|
|
type 'a t
|
|
|
|
val empty : 'a t
|
|
|
|
val is_empty : _ t -> bool
|
|
|
|
val singleton : key -> 'a -> 'a t
|
|
|
|
val add : key -> 'a -> 'a t -> 'a t
|
|
|
|
val mem : key -> _ t -> bool
|
|
|
|
val get : key -> 'a t -> 'a option
|
|
|
|
val get_exn : key -> 'a t -> 'a
|
|
(** @raise Not_found if key not present. *)
|
|
|
|
val remove : key -> 'a t -> 'a t
|
|
(** Remove the key, if present. *)
|
|
|
|
val update : key -> f:('a option -> 'a option) -> 'a t -> 'a t
|
|
(** [update k ~f m] calls [f (Some v)] if [get k m = Some v], [f None]
|
|
otherwise. Then, if [f] returns [Some v'] it binds [k] to [v'],
|
|
if [f] returns [None] it removes [k]. *)
|
|
|
|
val add_mut : id:Transient.t -> key -> 'a -> 'a t -> 'a t
|
|
(** [add_mut ~id k v m] behaves like [add k v m], except it will mutate
|
|
in place whenever possible. Changes done with an [id] might affect all
|
|
versions of the structure obtained with the same [id] (but not
|
|
other versions).
|
|
@raise Transient.Frozen if [id] is frozen. *)
|
|
|
|
val remove_mut : id:Transient.t -> key -> 'a t -> 'a t
|
|
(** Same as {!remove}, but modifies in place whenever possible.
|
|
@raise Transient.Frozen if [id] is frozen. *)
|
|
|
|
val update_mut : id:Transient.t -> key -> f:('a option -> 'a option) -> 'a t -> 'a t
|
|
(** Same as {!update} but with mutability.
|
|
@raise Transient.Frozen if [id] is frozen. *)
|
|
|
|
val cardinal : _ t -> int
|
|
|
|
val choose : 'a t -> (key * 'a) option
|
|
|
|
val choose_exn : 'a t -> key * 'a
|
|
(** @raise Not_found if not pair was found. *)
|
|
|
|
val iter : f:(key -> 'a -> unit) -> 'a t -> unit
|
|
|
|
val fold : f:('b -> key -> 'a -> 'b) -> x:'b -> 'a t -> 'b
|
|
|
|
(** {5 Conversions} *)
|
|
|
|
val to_list : 'a t -> (key * 'a) list
|
|
|
|
val add_list : 'a t -> (key * 'a) list -> 'a t
|
|
|
|
val add_list_mut : id:Transient.t -> 'a t -> (key * 'a) list -> 'a t
|
|
(** @raise Frozen if the ID is frozen. *)
|
|
|
|
val of_list : (key * 'a) list -> 'a t
|
|
|
|
val add_iter : 'a t -> (key * 'a) iter -> 'a t
|
|
|
|
val add_iter_mut : id:Transient.t -> 'a t -> (key * 'a) iter -> 'a t
|
|
(** @raise Frozen if the ID is frozen. *)
|
|
|
|
val of_iter : (key * 'a) iter -> 'a t
|
|
|
|
val to_iter : 'a t -> (key * 'a) iter
|
|
|
|
val add_gen : 'a t -> (key * 'a) gen -> 'a t
|
|
|
|
val add_gen_mut : id:Transient.t -> 'a t -> (key * 'a) gen -> 'a t
|
|
(** @raise Frozen if the ID is frozen. *)
|
|
|
|
val of_gen : (key * 'a) gen -> 'a t
|
|
|
|
val to_gen : 'a t -> (key * 'a) gen
|
|
|
|
(** {5 IO} *)
|
|
|
|
val pp : key printer -> 'a printer -> 'a t printer
|
|
(** Renamed from [val print].
|
|
@since 2.0 *)
|
|
|
|
val as_tree : 'a t -> [`L of int * (key * 'a) list | `N ] ktree
|
|
(** For debugging purpose: explore the structure of the tree,
|
|
with [`L (h,l)] being a leaf (with shared hash [h])
|
|
and [`N] an inner node. *)
|
|
end
|
|
|
|
(** {2 Type for keys} *)
|
|
module type KEY = sig
|
|
type t
|
|
val equal : t -> t -> bool
|
|
val hash : t -> int
|
|
end
|
|
|
|
(** {2 Functors} *)
|
|
module Make(K : KEY) : S with type key = K.t
|
|
|
|
(**/**)
|
|
val popcount : int64 -> int
|
|
(**/**)
|