mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-08 20:25:28 -05:00
274 lines
4.7 KiB
OCaml
274 lines
4.7 KiB
OCaml
(* This file is free software, part of containers. See file "license" for more details. *)
|
|
|
|
(** {1 Options} *)
|
|
|
|
type 'a t = 'a option
|
|
|
|
let[@inline] map f = function
|
|
| None -> None
|
|
| Some x -> Some (f x)
|
|
|
|
let map_or ~default f = function
|
|
| None -> default
|
|
| Some x -> f x
|
|
|
|
let map_lazy default_fn f = function
|
|
| None -> default_fn ()
|
|
| Some x -> f x
|
|
|
|
let is_some = function
|
|
| None -> false
|
|
| Some _ -> true
|
|
|
|
let is_none = function
|
|
| None -> true
|
|
| Some _ -> false
|
|
|
|
let compare f o1 o2 =
|
|
match o1, o2 with
|
|
| None, None -> 0
|
|
| Some _, None -> 1
|
|
| None, Some _ -> -1
|
|
| Some x, Some y -> f x y
|
|
|
|
let equal f o1 o2 =
|
|
match o1, o2 with
|
|
| None, None -> true
|
|
| Some _, None | None, Some _ -> false
|
|
| Some x, Some y -> f x y
|
|
|
|
let return x = Some x
|
|
let some = return
|
|
let none = None
|
|
|
|
let[@inline] flat_map f o =
|
|
match o with
|
|
| None -> None
|
|
| Some x -> f x
|
|
|
|
let[@inline] flat_map_l f o =
|
|
match o with
|
|
| None -> []
|
|
| Some x -> f x
|
|
|
|
let[@inline] bind o f = flat_map f o
|
|
let ( >>= ) = bind
|
|
let pure x = Some x
|
|
let k_compose f g x = f x |> flat_map g
|
|
let ( >=> ) = k_compose
|
|
let ( <=< ) f g = g >=> f
|
|
|
|
let ( <*> ) f x =
|
|
match f, x with
|
|
| None, _ | _, None -> None
|
|
| Some f, Some x -> Some (f x)
|
|
|
|
let or_ ~else_ a =
|
|
match a with
|
|
| None -> else_
|
|
| Some _ -> a
|
|
|
|
let or_lazy ~else_ a =
|
|
match a with
|
|
| None -> else_ ()
|
|
| Some _ -> a
|
|
|
|
let ( <+> ) a b = or_ ~else_:b a
|
|
let choice l = List.fold_left ( <+> ) None l
|
|
|
|
let map2 f o1 o2 =
|
|
match o1, o2 with
|
|
| None, _ | _, None -> None
|
|
| Some x, Some y -> Some (f x y)
|
|
|
|
let filter p = function
|
|
| Some x as o when p x -> o
|
|
| _ -> None
|
|
|
|
let if_ p x =
|
|
if p x then
|
|
Some x
|
|
else
|
|
None
|
|
|
|
let exists p = function
|
|
| None -> false
|
|
| Some x -> p x
|
|
|
|
let for_all p = function
|
|
| None -> true
|
|
| Some x -> p x
|
|
|
|
let iter f o =
|
|
match o with
|
|
| None -> ()
|
|
| Some x -> f x
|
|
|
|
let fold f acc o =
|
|
match o with
|
|
| None -> acc
|
|
| Some x -> f acc x
|
|
|
|
let get_or ~default x =
|
|
match x with
|
|
| None -> default
|
|
| Some y -> y
|
|
|
|
let apply_or f x =
|
|
match f x with
|
|
| None -> x
|
|
| Some y -> y
|
|
|
|
let ( |?> ) x f = apply_or f x
|
|
|
|
let value x ~default =
|
|
match x with
|
|
| None -> default
|
|
| Some y -> y
|
|
|
|
let get_exn = function
|
|
| Some x -> x
|
|
| None -> invalid_arg "CCOption.get_exn"
|
|
|
|
let get_exn_or msg = function
|
|
| Some x -> x
|
|
| None -> invalid_arg msg
|
|
|
|
let get_lazy default_fn x =
|
|
match x with
|
|
| None -> default_fn ()
|
|
| Some y -> y
|
|
|
|
let sequence_l l =
|
|
let rec aux acc l =
|
|
match l with
|
|
| [] -> Some (List.rev acc)
|
|
| Some x :: l' -> aux (x :: acc) l'
|
|
| None :: _ -> raise Exit
|
|
in
|
|
try aux [] l with Exit -> None
|
|
|
|
let wrap ?(handler = fun _ -> true) f x =
|
|
try Some (f x)
|
|
with e ->
|
|
if handler e then
|
|
None
|
|
else
|
|
raise e
|
|
|
|
let wrap2 ?(handler = fun _ -> true) f x y =
|
|
try Some (f x y)
|
|
with e ->
|
|
if handler e then
|
|
None
|
|
else
|
|
raise e
|
|
|
|
let to_list o =
|
|
match o with
|
|
| None -> []
|
|
| Some x -> [ x ]
|
|
|
|
let of_list = function
|
|
| x :: _ -> Some x
|
|
| [] -> None
|
|
|
|
let to_result err = function
|
|
| None -> Error err
|
|
| Some x -> Ok x
|
|
|
|
let to_result_lazy err_fn = function
|
|
| None -> Error (err_fn ())
|
|
| Some x -> Ok x
|
|
|
|
let of_result = function
|
|
| Error _ -> None
|
|
| Ok x -> Some x
|
|
|
|
module Infix = struct
|
|
let ( >|= ) x f = map f x
|
|
let ( >>= ) = ( >>= )
|
|
let ( <*> ) = ( <*> )
|
|
let ( <$> ) = map
|
|
let ( <+> ) = ( <+> )
|
|
let ( |?> ) = ( |?> )
|
|
let ( let+ ) = ( >|= )
|
|
let ( let* ) = ( >>= )
|
|
|
|
let[@inline] ( and+ ) o1 o2 =
|
|
match o1, o2 with
|
|
| Some x, Some y -> Some (x, y)
|
|
| _ -> None
|
|
|
|
let ( and* ) = ( and+ )
|
|
let ( >=> ) = ( >=> )
|
|
let ( <=< ) = ( <=< )
|
|
end
|
|
|
|
include Infix
|
|
|
|
type 'a iter = ('a -> unit) -> unit
|
|
type 'a gen = unit -> 'a option
|
|
type 'a printer = Format.formatter -> 'a -> unit
|
|
type 'a random_gen = Random.State.t -> 'a
|
|
|
|
let random g st =
|
|
if Random.State.bool st then
|
|
Some (g st)
|
|
else
|
|
None
|
|
|
|
exception ExitChoice
|
|
|
|
let choice_iter s =
|
|
let r = ref None in
|
|
(try
|
|
s (function
|
|
| None -> ()
|
|
| Some _ as o ->
|
|
r := o;
|
|
raise ExitChoice)
|
|
with ExitChoice -> ());
|
|
!r
|
|
|
|
let rec choice_seq s =
|
|
match s () with
|
|
| Seq.Nil -> None
|
|
| Seq.Cons (Some x, _) -> Some x
|
|
| Seq.Cons (None, tl) -> choice_seq tl
|
|
|
|
let to_gen o =
|
|
match o with
|
|
| None -> fun () -> None
|
|
| Some _ ->
|
|
let first = ref true in
|
|
fun () ->
|
|
if !first then (
|
|
first := false;
|
|
o
|
|
) else
|
|
None
|
|
|
|
let to_iter o k =
|
|
match o with
|
|
| None -> ()
|
|
| Some x -> k x
|
|
|
|
let to_seq o () =
|
|
match o with
|
|
| None -> Seq.Nil
|
|
| Some x -> Seq.Cons (x, Seq.empty)
|
|
|
|
let pp ppx out = function
|
|
| None -> Format.pp_print_string out "None"
|
|
| Some x -> Format.fprintf out "@[Some %a@]" ppx x
|
|
|
|
let flatten = function
|
|
| Some x -> x
|
|
| None -> None
|
|
|
|
let return_if b x =
|
|
if b then
|
|
Some x
|
|
else
|
|
None
|