ocaml-containers/src/core/CCOption.ml
Simon Cruanes cb14c0d04b
format
2024-07-19 14:04:00 -04:00

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