ocaml-containers/src/core/CCSet.ml
2023-06-06 22:16:20 -04:00

208 lines
5 KiB
OCaml

(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Wrapper around Set} *)
type 'a iter = ('a -> unit) -> unit
type 'a printer = Format.formatter -> 'a -> unit
module type OrderedType = Set.OrderedType
module type S = sig
include Set.S
val min_elt_opt : t -> elt option
(** Safe version of {!min_elt}.
@since 1.5 *)
val max_elt_opt : t -> elt option
(** Safe version of {!max_elt}.
@since 1.5 *)
val choose_opt : t -> elt option
(** Safe version of {!choose}.
@since 1.5 *)
val find_opt : elt -> t -> elt option
(** Safe version of {!find}.
@since 1.5 *)
val find_first : (elt -> bool) -> t -> elt
(** Find minimum element satisfying predicate.
@since 1.5 *)
val find_first_opt : (elt -> bool) -> t -> elt option
(** Safe version of {!find_first}.
@since 1.5 *)
val find_first_map : (elt -> 'a option) -> t -> 'a option
(** [find_first_map f s] find the minimum element [x] of [s] such that [f x = Some y]
and return [Some y]. Otherwise returns [None].
@since 3.12 *)
val find_last : (elt -> bool) -> t -> elt
(** Find maximum element satisfying predicate.
@since 1.5 *)
val find_last_opt : (elt -> bool) -> t -> elt option
(** Safe version of {!find_last}.
@since 1.5 *)
val find_last_map : (elt -> 'a option) -> t -> 'a option
(** [find_last_map f s] find the maximum element [x] of [s] such that [f x = Some y]
and return [Some y]. Otherwise returns [None].
@since 3.12 *)
val of_iter : elt iter -> t
(** Build a set from the given [iter] of elements.
@since 2.8 *)
val of_seq : elt Seq.t -> t
(** Build a set from the given [seq] of elements.
@since 3.0 *)
val add_iter : t -> elt iter -> t
(** @since 2.8 *)
val add_seq : elt Seq.t -> t -> t
(** @since 3.0 *)
val to_iter : t -> elt iter
(** [to_iter t] converts the set [t] to a [iter] of the elements.
@since 2.8 *)
val add_list : t -> elt list -> t
(** @since 0.14 *)
val to_list : t -> elt list
(** [to_list t] converts the set [t] to a list of the elements. *)
val to_string :
?start:string ->
?stop:string ->
?sep:string ->
(elt -> string) ->
t ->
string
(** Print the set in a string
@since 2.7 *)
val pp :
?pp_start:unit printer ->
?pp_stop:unit printer ->
?pp_sep:unit printer ->
elt printer ->
t printer
(** Print the set. *)
end
module Make (O : Map.OrderedType) = struct
module S = Set.Make (O)
(* backport functions from recent stdlib.
they will be shadowed by inclusion of [S] if present. *)
[@@@ocaml.warning "-32"]
let find_opt x s = try Some (S.find x s) with Not_found -> None
let choose_opt s = try Some (S.choose s) with Not_found -> None
let min_elt_opt s = try Some (S.min_elt s) with Not_found -> None
let max_elt_opt s = try Some (S.max_elt s) with Not_found -> None
exception Find_binding_exit
let find_first_opt f m =
let res = ref None in
try
S.iter
(fun x ->
if f x then (
res := Some x;
raise Find_binding_exit
))
m;
None
with Find_binding_exit -> !res
let find_first f m =
match find_first_opt f m with
| None -> raise Not_found
| Some x -> x
let find_first_map f m =
let res = ref None in
try
S.iter
(fun x ->
match f x with
| None -> ()
| Some y ->
res := Some y;
raise Find_binding_exit)
m;
None
with Find_binding_exit -> !res
(* linear time, must traverse the whole set… *)
let find_last_opt f m =
let res = ref None in
S.iter (fun x -> if f x then res := Some x) m;
!res
let find_last f m =
match find_last_opt f m with
| None -> raise Not_found
| Some x -> x
[@@@ocaml.warning "+32"]
include S
(* Use find_last which is linear time on OCaml < 4.05 *)
let find_last_map f m =
let res = ref None in
let _ =
find_last_opt
(fun x ->
match f x with
| None -> false
| Some y ->
res := Some y;
true)
m
in
!res
let add_seq seq set =
let set = ref set in
Seq.iter (fun x -> set := add x !set) seq;
!set
let of_seq s = add_seq s empty
let add_iter set i =
let set = ref set in
i (fun x -> set := add x !set);
!set
let of_iter s = add_iter empty s
let to_iter s yield = iter yield s
let add_list = List.fold_left (fun set x -> add x set)
let to_list = elements
let to_string ?(start = "") ?(stop = "") ?(sep = ",") elt_to_string h =
to_list h |> CCList.to_string ~start ~stop ~sep elt_to_string
let pp ?(pp_start = fun _ () -> ()) ?(pp_stop = fun _ () -> ())
?(pp_sep = fun fmt () -> Format.fprintf fmt ",@ ") pp_x fmt m =
pp_start fmt ();
let first = ref true in
iter
(fun x ->
if !first then
first := false
else
pp_sep fmt ();
pp_x fmt x)
m;
pp_stop fmt ()
end