chore(CCOption): rename CCOpt to CCOption and deprecate CCOpt

In the stdlib the module associated with the option type is called
Option and in containers it was called CCOpt. Renaming CCOpt to CCOption
make the name of containers module uniforme with respect to the stdlib.
This commit is contained in:
Fardale 2021-09-22 23:03:19 +02:00
parent 27e39a0fc8
commit 302dba6cb5
17 changed files with 540 additions and 536 deletions

View file

@ -427,7 +427,7 @@ map =
- : unit = () - : unit = ()
# (* options are good *) # (* options are good *)
IntMap.get 3 map |> CCOpt.map (fun s->s ^ s);; IntMap.get 3 map |> CCOption.map (fun s->s ^ s);;
- : string option = Some "33" - : string option = Some "33"
``` ```

View file

@ -1073,7 +1073,7 @@ let sublists_of_len ?(last=fun _ -> None) ?offset n l =
[[1;2];[3;4]] (subs ~offset:2 2 [1;2;3;4]) [[1;2];[3;4]] (subs ~offset:2 2 [1;2;3;4])
[[1;2];[2;3]] (subs ~offset:1 2 [1;2;3]) [[1;2];[2;3]] (subs ~offset:1 2 [1;2;3])
[[1;2];[4;5]] (subs ~offset:3 2 [1;2;3;4;5;6]) [[1;2];[4;5]] (subs ~offset:3 2 [1;2;3;4;5;6])
[[1;2;3];[4]] (subs ~last:CCOpt.return 3 [1;2;3;4]) [[1;2;3];[4]] (subs ~last:CCOption.return 3 [1;2;3;4])
[[1;2]; [3;4]] (subs 2 [1;2;3;4;5]) [[1;2]; [3;4]] (subs 2 [1;2;3;4;5])
*) *)

View file

@ -324,7 +324,7 @@ val sublists_of_len :
- [sublists_of_len 2 [1;2;3;4;5;6] = [[1;2]; [3;4]; [5;6]]]. - [sublists_of_len 2 [1;2;3;4;5;6] = [[1;2]; [3;4]; [5;6]]].
- [sublists_of_len 2 ~offset:3 [1;2;3;4;5;6] = [1;2];[4;5]]. - [sublists_of_len 2 ~offset:3 [1;2;3;4;5;6] = [1;2];[4;5]].
- [sublists_of_len 3 ~last:CCOpt.return [1;2;3;4] = [1;2;3];[4]]. - [sublists_of_len 3 ~last:CCOption.return [1;2;3;4] = [1;2;3];[4]].
- [sublists_of_len 2 [1;2;3;4;5] = [[1;2]; [3;4]]]. - [sublists_of_len 2 [1;2;3;4;5] = [[1;2]; [3;4]]].
@param offset the number of elements skipped between two consecutive @param offset the number of elements skipped between two consecutive
@ -333,7 +333,7 @@ val sublists_of_len :
@param last if provided and the last group of elements [g] is such @param last if provided and the last group of elements [g] is such
that [length g < n], [last g] is called. If [last g = Some g'], that [length g < n], [last g] is called. If [last g = Some g'],
[g'] is appended; otherwise [g] is dropped. [g'] is appended; otherwise [g] is dropped.
If [last = CCOpt.return], it will simply keep the last group. If [last = CCOption.return], it will simply keep the last group.
By default, [last = fun _ -> None], i.e. the last group is dropped if shorter than [n]. By default, [last = fun _ -> None], i.e. the last group is dropped if shorter than [n].
@raise Invalid_argument if [offset <= 0] or [n <= 0]. @raise Invalid_argument if [offset <= 0] or [n <= 0].
See {!CCList.sublists_of_len} for more details. See {!CCList.sublists_of_len} for more details.

View file

@ -327,7 +327,7 @@ val sublists_of_len :
- [sublists_of_len 2 [1;2;3;4;5;6] = [[1;2]; [3;4]; [5;6]]]. - [sublists_of_len 2 [1;2;3;4;5;6] = [[1;2]; [3;4]; [5;6]]].
- [sublists_of_len 2 ~offset:3 [1;2;3;4;5;6] = [1;2];[4;5]]. - [sublists_of_len 2 ~offset:3 [1;2;3;4;5;6] = [1;2];[4;5]].
- [sublists_of_len 3 ~last:CCOpt.return [1;2;3;4] = [1;2;3];[4]]. - [sublists_of_len 3 ~last:CCOption.return [1;2;3;4] = [1;2;3];[4]].
- [sublists_of_len 2 [1;2;3;4;5] = [[1;2]; [3;4]]]. - [sublists_of_len 2 [1;2;3;4;5] = [[1;2]; [3;4]]].
@param offset the number of elements skipped between two consecutive @param offset the number of elements skipped between two consecutive
@ -336,7 +336,7 @@ val sublists_of_len :
@param last if provided and the last group of elements [g] is such @param last if provided and the last group of elements [g] is such
that [length g < n], [last g] is called. If [last g = Some g'], that [length g < n], [last g] is called. If [last g = Some g'],
[g'] is appended; otherwise [g] is dropped. [g'] is appended; otherwise [g] is dropped.
If [last = CCOpt.return], it will simply keep the last group. If [last = CCOption.return], it will simply keep the last group.
By default, [last = fun _ -> None], i.e. the last group is dropped if shorter than [n]. By default, [last = fun _ -> None], i.e. the last group is dropped if shorter than [n].
@raise Invalid_argument if [offset <= 0] or [n <= 0]. @raise Invalid_argument if [offset <= 0] or [n <= 0].
See {!CCList.sublists_of_len} for more details. See {!CCList.sublists_of_len} for more details.

View file

@ -243,7 +243,7 @@ module Make(O : Map.OrderedType) = struct
(M.of_list ["b", 2; "c", 3] \ (M.of_list ["b", 2; "c", 3] \
|> M.update "a" (function _ -> Some 1) \ |> M.update "a" (function _ -> Some 1) \
|> M.update "c" (fun _ -> None) \ |> M.update "c" (fun _ -> None) \
|> M.update "b" (CCOpt.map (fun x -> x * 10)) \ |> M.update "b" (CCOption.map (fun x -> x * 10)) \
|> M.to_list |> List.sort CCOrd.compare) |> M.to_list |> List.sort CCOrd.compare)
*) *)

View file

@ -1,269 +1 @@
(* This file is free software, part of containers. See file "license" for more details. *) include CCOption
(** {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] bind o f = flat_map f o
let (>>=) = bind
let pure x = Some x
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
(*$=
None (filter ((=) 0) (Some 1))
(Some 0) (filter ((=) 0) (Some 0))
None (filter (fun _ -> true) 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 value x ~default = match x with
| None -> default
| Some y -> y
let get_exn = function
| Some x -> x
| None -> invalid_arg "CCOpt.get_exn"
let get_exn_or msg = function
| Some x -> x
| None -> invalid_arg msg
(*$T
(try get_exn_or "ohno" (None:unit option); false with Invalid_argument s->s= "ohno")
123 = get_exn_or "yes" (Some 123)
*)
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
(*$T
sequence_l [None; Some 1; Some 2] = None
sequence_l [Some 1; Some 2; Some 3] = Some [1;2;3]
sequence_l [] = Some []
*)
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 (<+>) = (<+>)
include CCShimsMkLet_.Make(struct
type 'a t = 'a option
let (>|=) = (>|=)
let (>>=) = (>>=)
let[@inline] monoid_product o1 o2 = match o1, o2 with
| Some x, Some y -> Some (x,y)
| _ -> None
end)
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
begin try
s (function
| None -> ()
| (Some _) as o -> r := o; raise ExitChoice
)
with ExitChoice -> ()
end;
!r
(*$T
choice_iter (Iter.of_list [None; Some 1; Some 2]) = Some 1
choice_iter Iter.empty = None
choice_iter (Iter.repeat None |> Iter.take 100) = None
*)
let rec choice_seq s = match s() with
| Seq.Nil -> None
| Seq.Cons (Some x, _) -> Some x
| Seq.Cons (None, tl) -> choice_seq tl
(*$T
choice_seq (CCSeq.of_list [None; Some 1; Some 2]) = Some 1
choice_seq CCSeq.empty = None
choice_seq (CCSeq.repeat None |> CCSeq.take 100) = None
*)
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 = to_iter
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
(*$T
flatten None = None
flatten (Some None) = None
flatten (Some (Some 1)) = Some 1
*)
let return_if b x =
if b then
Some x
else
None
(*$T
return_if false 1 = None
return_if true 1 = Some 1
*)

View file

@ -1,250 +1,3 @@
(* This file is free software, part of containers. See file "license" for more details. *) [@@@ocaml.deprecated "use CCOption instead"]
(** {1 Options} *) include module type of CCOption
type +'a t = 'a option
val map : ('a -> 'b) -> 'a t -> 'b t
(** [map f o] applies the function [f] to the element inside [o], if any. *)
val map_or : default:'b -> ('a -> 'b) -> 'a t -> 'b
(** [map_or ~default f o] is [f x] if [o = Some x], [default] otherwise.
@since 0.16 *)
val map_lazy : (unit -> 'b) -> ('a -> 'b) -> 'a t -> 'b
(** [map_lazy default_fn f o] if [f o] if [o = Some x], [default_fn ()] otherwise.
@since 1.2 *)
val is_some : _ t -> bool
(** [is_some (Some x)] returns [true] otherwise it returns [false]. *)
val is_none : _ t -> bool
(** [is_none None] returns [true] otherwise it returns [false].
@since 0.11 *)
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
(** [compare comp o1 o2] compares two options [o1] and [o2],
using custom comparators [comp] for the value.
[None] is always assumed to be less than [Some _]. *)
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
(** [equal p o1 o2] tests for equality between option types [o1] and [o2],
using a custom equality predicate [p]. *)
val return : 'a -> 'a t
(** [return x] is a monadic return, that is [return x = Some x]. *)
val some : 'a -> 'a t
(** Alias to {!return}.
@since 3.5 *)
val none : 'a t
(** Alias to {!None}.
@since 3.5 *)
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** [o >|= f] is the infix version of {!map}. *)
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
(** [flat_map f o] is equivalent to {!map} followed by {!flatten}.
Flip version of {!>>=}. *)
val bind : 'a t -> ('a -> 'b t) -> 'b t
(** [bind o f] is [f v] if [o] is [Some v], [None] otherwise.
Monadic bind.
@since 3.0 *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
(** [o >>= f] is the infix version of {!bind}. *)
val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** [map2 f o1 o2] maps ['a option] and ['b option] to a ['c option] using [f]. *)
val iter : ('a -> unit) -> 'a t -> unit
(** [iter f o] applies [f] to [o]. Iterate on 0 or 1 element. *)
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** [fold f init o] is [f init x] if [o] is [Some x], or [init] if [o] is [None].
Fold on 0 or 1 element. *)
val filter : ('a -> bool) -> 'a t -> 'a t
(** [filter f o] returns [Some x] if [o] is [Some x] and [f x] is [true],
or [None] if [f x] is [false] or if [o] is [None].
Filter on 0 or 1 element.
@since 0.5 *)
val if_ : ('a -> bool) -> 'a -> 'a option
(** [if_ f x] is [Some x] if [f x], [None] otherwise.
@since 0.17 *)
val exists : ('a -> bool) -> 'a t -> bool
(** [exists f o] returns [true] iff there exists an element for which
the provided function [f] evaluates to [true].
@since 0.17 *)
val for_all : ('a -> bool) -> 'a t -> bool
(** [for_all f o] returns [true] iff the provided function [f] evaluates to [true] for all elements.
@since 0.17 *)
val get_or : default:'a -> 'a t -> 'a
(** [get_or ~default o] extracts the value from [o], or
returns [default] if [o] is [None].
@since 0.18 *)
val value : 'a t -> default:'a -> 'a
(** [value o ~default] is similar to the Stdlib's [Option.value] and to {!get_or}.
@since 2.8 *)
val get_exn : 'a t -> 'a
[@@ocaml.deprecated "use CCOpt.get_exn_or instead"]
(** [get_exn o] returns [x] if [o] is [Some x] or fails if [o] is [None].
@raise Invalid_argument if the option is [None].
@deprecated use {!get_exn_or} instead
*)
val get_exn_or : string -> 'a t -> 'a
(** [get_exn_or msg o] returns [x] if [o] is [Some x]
or fails with [Invalid_argument msg] if [o] is [None].
@raise Invalid_argument if the option is [None].
@since 3.4 *)
val get_lazy : (unit -> 'a) -> 'a t -> 'a
(** [get_lazy default_fn o] unwraps [o], but if [o] is [None] it returns [default_fn ()] instead.
@since 0.6.1 *)
val sequence_l : 'a t list -> 'a list t
(** [sequence_l [x1; x2; …; xn]] returns [Some [y1; y2; …; yn]] if
every [xi] is [Some yi]. Otherwise, if the list contains at least
one [None], the result is [None]. *)
val wrap : ?handler:(exn -> bool) -> ('a -> 'b) -> 'a -> 'b option
(** [wrap ?handler f x] calls [f x] and returns [Some y] if [f x = y]. If [f x] raises
any exception, the result is [None]. This can be useful to wrap functions
such as [Map.S.find].
@param handler the exception handler, which returns [true] if the
exception is to be caught. *)
val wrap2 : ?handler:(exn -> bool) -> ('a -> 'b -> 'c) -> 'a -> 'b -> 'c option
(** [wrap2 ?handler f x y] is similar to {!wrap} but for binary functions. *)
(** {2 Applicative} *)
val pure : 'a -> 'a t
(** [pure x] is an alias to {!return}. *)
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
(** [f <*> (Some x)] returns [Some (f x)] and [f <*> None] returns [None]. *)
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
(** [f <$> o] is like [map f o]. *)
(** {2 Alternatives} *)
val or_ : else_:('a t) -> 'a t -> 'a t
(** [or_ ~else_ o] is [o] if [o] is [Some _], [else_] if [o] is [None].
@since 1.2 *)
val or_lazy : else_:(unit -> 'a t) -> 'a t -> 'a t
(** [or_lazy ~else_ o] is [o] if [o] is [Some _], [else_ ()] if [o] is [None].
@since 1.2 *)
val (<+>) : 'a t -> 'a t -> 'a t
(** [o1 <+> o2] is [o1] if [o1] is [Some _], [o2] if [o1] is [None]. *)
val choice : 'a t list -> 'a t
(** [choice lo] returns the first non-[None] element of the list [lo], or [None]. *)
val flatten : 'a t t -> 'a t
(** [flatten oo] transforms [Some x] into [x].
@since 2.2 *)
val return_if : bool -> 'a -> 'a t
(** [return_if b x] applies [Some] or [None] depending on the boolean [b].
More precisely, [return_if false x] is [None],
and [return_if true x] is [Some x].
@since 2.2 *)
(** {2 Infix Operators}
@since 0.16 *)
module Infix : sig
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** [o >|= f] is [map f o]. *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
(** [o >>= f] is the monadic bind. *)
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
(** [f <*> o] returns [Some (f x)] if [o] is [Some x] and [None] if [o] is [None]. *)
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
(** [f <$> o] is like [map f o]. *)
val (<+>) : 'a t -> 'a t -> 'a t
(** [o1 <+> o2] is [o1] if [o1] is [Some _], [o2] if [o1] is [None]. *)
(** Let operators on OCaml >= 4.08.0, nothing otherwise
@since 2.8 *)
include CCShimsMkLet_.S with type 'a t_let := 'a option
end
(** Let operators on OCaml >= 4.08.0, nothing otherwise
@since 2.8 *)
include CCShimsMkLet_.S with type 'a t_let := 'a option
(** {2 Conversion and IO} *)
val to_list : 'a t -> 'a list
(** [to_list o] returns [[x]] if [o] is [Some x] or the empty list [[]] if [o] is [None]. *)
val of_list : 'a list -> 'a t
(** [of_list l] returns [Some x] (x being the head of the list l), or [None] if [l] is the empty list. *)
val to_result : 'e -> 'a t -> ('a, 'e) result
(** [to_result e o] returns [Ok x] if [o] is [Some x], or [Error e] if [o] is [None].
@since 1.2 *)
val to_result_lazy : (unit -> 'e) -> 'a t -> ('a, 'e) result
(** [to_result_lazy f o] returns [Ok x] if [o] is [Some x] or [Error f] if [o] is [None].
@since 1.2 *)
val of_result : ('a, _) result -> 'a t
(** [of_result result] returns an option from a [result].
@since 1.2 *)
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
val random : 'a random_gen -> 'a t random_gen
val choice_iter : 'a t iter -> 'a t
(** [choice_iter iter] is similar to {!choice}, but works on [iter].
It returns the first [Some x] occurring in [iter], or [None] otherwise.
@since 3.0 *)
val choice_seq : 'a t Seq.t -> 'a t
(** [choice_seq seq] works on [Seq.t].
It returns the first [Some x] occurring in [seq], or [None] otherwise.
@since 3.0 *)
val to_gen : 'a t -> 'a gen
(** [to_gen o] is [o] as a [gen]. [Some x] is the singleton [gen] containing [x]
and [None] is the empty [gen]. *)
val to_seq : 'a t -> 'a Seq.t
(** [to_seq o] is [o] as a sequence [Seq.t]. [Some x] is the singleton sequence containing [x]
and [None] is the empty sequence.
Same as {!Stdlib.Option.to_seq}
Renamed from [to_std_seq] since 3.0.
@since 3.0 *)
val to_iter : 'a t -> 'a iter
(** [to_iter o] returns an internal iterator, like in the library [Iter].
@since 2.8 *)
val pp : 'a printer -> 'a t printer
(** [pp ppf o] pretty-prints option [o] using [ppf]. *)

269
src/core/CCOption.ml Normal file
View file

@ -0,0 +1,269 @@
(* 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] bind o f = flat_map f o
let (>>=) = bind
let pure x = Some x
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
(*$=
None (filter ((=) 0) (Some 1))
(Some 0) (filter ((=) 0) (Some 0))
None (filter (fun _ -> true) 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 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
(*$T
(try get_exn_or "ohno" (None:unit option); false with Invalid_argument s->s= "ohno")
123 = get_exn_or "yes" (Some 123)
*)
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
(*$T
sequence_l [None; Some 1; Some 2] = None
sequence_l [Some 1; Some 2; Some 3] = Some [1;2;3]
sequence_l [] = Some []
*)
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 (<+>) = (<+>)
include CCShimsMkLet_.Make(struct
type 'a t = 'a option
let (>|=) = (>|=)
let (>>=) = (>>=)
let[@inline] monoid_product o1 o2 = match o1, o2 with
| Some x, Some y -> Some (x,y)
| _ -> None
end)
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
begin try
s (function
| None -> ()
| (Some _) as o -> r := o; raise ExitChoice
)
with ExitChoice -> ()
end;
!r
(*$T
choice_iter (Iter.of_list [None; Some 1; Some 2]) = Some 1
choice_iter Iter.empty = None
choice_iter (Iter.repeat None |> Iter.take 100) = None
*)
let rec choice_seq s = match s() with
| Seq.Nil -> None
| Seq.Cons (Some x, _) -> Some x
| Seq.Cons (None, tl) -> choice_seq tl
(*$T
choice_seq (CCSeq.of_list [None; Some 1; Some 2]) = Some 1
choice_seq CCSeq.empty = None
choice_seq (CCSeq.repeat None |> CCSeq.take 100) = None
*)
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 = to_iter
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
(*$T
flatten None = None
flatten (Some None) = None
flatten (Some (Some 1)) = Some 1
*)
let return_if b x =
if b then
Some x
else
None
(*$T
return_if false 1 = None
return_if true 1 = Some 1
*)

250
src/core/CCOption.mli Normal file
View file

@ -0,0 +1,250 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Options} *)
type +'a t = 'a option
val map : ('a -> 'b) -> 'a t -> 'b t
(** [map f o] applies the function [f] to the element inside [o], if any. *)
val map_or : default:'b -> ('a -> 'b) -> 'a t -> 'b
(** [map_or ~default f o] is [f x] if [o = Some x], [default] otherwise.
@since 0.16 *)
val map_lazy : (unit -> 'b) -> ('a -> 'b) -> 'a t -> 'b
(** [map_lazy default_fn f o] if [f o] if [o = Some x], [default_fn ()] otherwise.
@since 1.2 *)
val is_some : _ t -> bool
(** [is_some (Some x)] returns [true] otherwise it returns [false]. *)
val is_none : _ t -> bool
(** [is_none None] returns [true] otherwise it returns [false].
@since 0.11 *)
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
(** [compare comp o1 o2] compares two options [o1] and [o2],
using custom comparators [comp] for the value.
[None] is always assumed to be less than [Some _]. *)
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
(** [equal p o1 o2] tests for equality between option types [o1] and [o2],
using a custom equality predicate [p]. *)
val return : 'a -> 'a t
(** [return x] is a monadic return, that is [return x = Some x]. *)
val some : 'a -> 'a t
(** Alias to {!return}.
@since 3.5 *)
val none : 'a t
(** Alias to {!None}.
@since 3.5 *)
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** [o >|= f] is the infix version of {!map}. *)
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
(** [flat_map f o] is equivalent to {!map} followed by {!flatten}.
Flip version of {!>>=}. *)
val bind : 'a t -> ('a -> 'b t) -> 'b t
(** [bind o f] is [f v] if [o] is [Some v], [None] otherwise.
Monadic bind.
@since 3.0 *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
(** [o >>= f] is the infix version of {!bind}. *)
val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
(** [map2 f o1 o2] maps ['a option] and ['b option] to a ['c option] using [f]. *)
val iter : ('a -> unit) -> 'a t -> unit
(** [iter f o] applies [f] to [o]. Iterate on 0 or 1 element. *)
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** [fold f init o] is [f init x] if [o] is [Some x], or [init] if [o] is [None].
Fold on 0 or 1 element. *)
val filter : ('a -> bool) -> 'a t -> 'a t
(** [filter f o] returns [Some x] if [o] is [Some x] and [f x] is [true],
or [None] if [f x] is [false] or if [o] is [None].
Filter on 0 or 1 element.
@since 0.5 *)
val if_ : ('a -> bool) -> 'a -> 'a option
(** [if_ f x] is [Some x] if [f x], [None] otherwise.
@since 0.17 *)
val exists : ('a -> bool) -> 'a t -> bool
(** [exists f o] returns [true] iff there exists an element for which
the provided function [f] evaluates to [true].
@since 0.17 *)
val for_all : ('a -> bool) -> 'a t -> bool
(** [for_all f o] returns [true] iff the provided function [f] evaluates to [true] for all elements.
@since 0.17 *)
val get_or : default:'a -> 'a t -> 'a
(** [get_or ~default o] extracts the value from [o], or
returns [default] if [o] is [None].
@since 0.18 *)
val value : 'a t -> default:'a -> 'a
(** [value o ~default] is similar to the Stdlib's [Option.value] and to {!get_or}.
@since 2.8 *)
val get_exn : 'a t -> 'a
[@@ocaml.deprecated "use CCOption.get_exn_or instead"]
(** [get_exn o] returns [x] if [o] is [Some x] or fails if [o] is [None].
@raise Invalid_argument if the option is [None].
@deprecated use {!get_exn_or} instead
*)
val get_exn_or : string -> 'a t -> 'a
(** [get_exn_or msg o] returns [x] if [o] is [Some x]
or fails with [Invalid_argument msg] if [o] is [None].
@raise Invalid_argument if the option is [None].
@since 3.4 *)
val get_lazy : (unit -> 'a) -> 'a t -> 'a
(** [get_lazy default_fn o] unwraps [o], but if [o] is [None] it returns [default_fn ()] instead.
@since 0.6.1 *)
val sequence_l : 'a t list -> 'a list t
(** [sequence_l [x1; x2; …; xn]] returns [Some [y1; y2; …; yn]] if
every [xi] is [Some yi]. Otherwise, if the list contains at least
one [None], the result is [None]. *)
val wrap : ?handler:(exn -> bool) -> ('a -> 'b) -> 'a -> 'b option
(** [wrap ?handler f x] calls [f x] and returns [Some y] if [f x = y]. If [f x] raises
any exception, the result is [None]. This can be useful to wrap functions
such as [Map.S.find].
@param handler the exception handler, which returns [true] if the
exception is to be caught. *)
val wrap2 : ?handler:(exn -> bool) -> ('a -> 'b -> 'c) -> 'a -> 'b -> 'c option
(** [wrap2 ?handler f x y] is similar to {!wrap} but for binary functions. *)
(** {2 Applicative} *)
val pure : 'a -> 'a t
(** [pure x] is an alias to {!return}. *)
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
(** [f <*> (Some x)] returns [Some (f x)] and [f <*> None] returns [None]. *)
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
(** [f <$> o] is like [map f o]. *)
(** {2 Alternatives} *)
val or_ : else_:('a t) -> 'a t -> 'a t
(** [or_ ~else_ o] is [o] if [o] is [Some _], [else_] if [o] is [None].
@since 1.2 *)
val or_lazy : else_:(unit -> 'a t) -> 'a t -> 'a t
(** [or_lazy ~else_ o] is [o] if [o] is [Some _], [else_ ()] if [o] is [None].
@since 1.2 *)
val (<+>) : 'a t -> 'a t -> 'a t
(** [o1 <+> o2] is [o1] if [o1] is [Some _], [o2] if [o1] is [None]. *)
val choice : 'a t list -> 'a t
(** [choice lo] returns the first non-[None] element of the list [lo], or [None]. *)
val flatten : 'a t t -> 'a t
(** [flatten oo] transforms [Some x] into [x].
@since 2.2 *)
val return_if : bool -> 'a -> 'a t
(** [return_if b x] applies [Some] or [None] depending on the boolean [b].
More precisely, [return_if false x] is [None],
and [return_if true x] is [Some x].
@since 2.2 *)
(** {2 Infix Operators}
@since 0.16 *)
module Infix : sig
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
(** [o >|= f] is [map f o]. *)
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
(** [o >>= f] is the monadic bind. *)
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
(** [f <*> o] returns [Some (f x)] if [o] is [Some x] and [None] if [o] is [None]. *)
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
(** [f <$> o] is like [map f o]. *)
val (<+>) : 'a t -> 'a t -> 'a t
(** [o1 <+> o2] is [o1] if [o1] is [Some _], [o2] if [o1] is [None]. *)
(** Let operators on OCaml >= 4.08.0, nothing otherwise
@since 2.8 *)
include CCShimsMkLet_.S with type 'a t_let := 'a option
end
(** Let operators on OCaml >= 4.08.0, nothing otherwise
@since 2.8 *)
include CCShimsMkLet_.S with type 'a t_let := 'a option
(** {2 Conversion and IO} *)
val to_list : 'a t -> 'a list
(** [to_list o] returns [[x]] if [o] is [Some x] or the empty list [[]] if [o] is [None]. *)
val of_list : 'a list -> 'a t
(** [of_list l] returns [Some x] (x being the head of the list l), or [None] if [l] is the empty list. *)
val to_result : 'e -> 'a t -> ('a, 'e) result
(** [to_result e o] returns [Ok x] if [o] is [Some x], or [Error e] if [o] is [None].
@since 1.2 *)
val to_result_lazy : (unit -> 'e) -> 'a t -> ('a, 'e) result
(** [to_result_lazy f o] returns [Ok x] if [o] is [Some x] or [Error f] if [o] is [None].
@since 1.2 *)
val of_result : ('a, _) result -> 'a t
(** [of_result result] returns an option from a [result].
@since 1.2 *)
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
val random : 'a random_gen -> 'a t random_gen
val choice_iter : 'a t iter -> 'a t
(** [choice_iter iter] is similar to {!choice}, but works on [iter].
It returns the first [Some x] occurring in [iter], or [None] otherwise.
@since 3.0 *)
val choice_seq : 'a t Seq.t -> 'a t
(** [choice_seq seq] works on [Seq.t].
It returns the first [Some x] occurring in [seq], or [None] otherwise.
@since 3.0 *)
val to_gen : 'a t -> 'a gen
(** [to_gen o] is [o] as a [gen]. [Some x] is the singleton [gen] containing [x]
and [None] is the empty [gen]. *)
val to_seq : 'a t -> 'a Seq.t
(** [to_seq o] is [o] as a sequence [Seq.t]. [Some x] is the singleton sequence containing [x]
and [None] is the empty sequence.
Same as {!Stdlib.Option.to_seq}
Renamed from [to_std_seq] since 3.0.
@since 3.0 *)
val to_iter : 'a t -> 'a iter
(** [to_iter o] returns an internal iterator, like in the library [Iter].
@since 2.8 *)
val pp : 'a printer -> 'a t printer
(** [pp ppf o] pretty-prints option [o] using [ppf]. *)

View file

@ -93,7 +93,7 @@ val get_or : ('a, _) t -> default:'a -> 'a
val get_lazy : ('e -> 'a) -> ('a, 'e) t -> 'a val get_lazy : ('e -> 'a) -> ('a, 'e) t -> 'a
(** [get_lazy f e] returns [x] if [e = Ok x], [f msg] if [e = Error msg]. (** [get_lazy f e] returns [x] if [e = Ok x], [f msg] if [e = Error msg].
This is similar to {!CCOpt.get_lazy}. This is similar to {!CCOption.get_lazy}.
@since 3.0 *) @since 3.0 *)
val get_or_failwith : ('a, string) t -> 'a val get_or_failwith : ('a, string) t -> 'a

View file

@ -345,7 +345,7 @@ let rec append_gen a b = match b() with
(*$inject (*$inject
let gen x = let gen x =
let small = length in let small = length in
let print = CCOpt.map (fun p x -> Q.Print.list p (CCVector.to_list x)) x.Q.print in let print = CCOption.map (fun p x -> Q.Print.list p (CCVector.to_list x)) x.Q.print in
Q.make ?print ~small Q.Gen.(list x.Q.gen >|= of_list) Q.make ?print ~small Q.Gen.(list x.Q.gen >|= of_list)
*) *)

View file

@ -32,7 +32,7 @@ module IO = CCIO
module List = CCList module List = CCList
module Map = CCMap module Map = CCMap
module Nativeint = CCNativeint module Nativeint = CCNativeint
module Option = CCOpt module Option = CCOption
module Ord = CCOrd module Ord = CCOrd
module Pair = CCPair module Pair = CCPair
module Parse = CCParse module Parse = CCParse

View file

@ -32,7 +32,7 @@ module IO = CCIO
module List = CCListLabels module List = CCListLabels
module Map = CCMap module Map = CCMap
module Nativeint = CCNativeint module Nativeint = CCNativeint
module Option = CCOpt module Option = CCOption
module Ord = CCOrd module Ord = CCOrd
module Pair = CCPair module Pair = CCPair
module Parse = CCParse module Parse = CCParse

View file

@ -347,15 +347,15 @@ let topo_sort ~eq ?rev ~tbl ~graph iter =
let tbl = mk_table ~eq:CCInt.equal 128 in \ let tbl = mk_table ~eq:CCInt.equal 128 in \
let l = topo_sort ~eq:CCInt.equal ~tbl ~graph:divisors_graph (Iter.return 42) in \ let l = topo_sort ~eq:CCInt.equal ~tbl ~graph:divisors_graph (Iter.return 42) in \
List.for_all (fun (i,j) -> \ List.for_all (fun (i,j) -> \
let idx_i = CCList.find_idx ((=)i) l |> CCOpt.get_exn |> fst in \ let idx_i = CCList.find_idx ((=)i) l |> CCOption.get_exn |> fst in \
let idx_j = CCList.find_idx ((=)j) l |> CCOpt.get_exn |> fst in \ let idx_j = CCList.find_idx ((=)j) l |> CCOption.get_exn |> fst in \
idx_i < idx_j) \ idx_i < idx_j) \
[ 42, 21; 14, 2; 3, 1; 21, 7; 42, 3] [ 42, 21; 14, 2; 3, 1; 21, 7; 42, 3]
let tbl = mk_table ~eq:CCInt.equal 128 in \ let tbl = mk_table ~eq:CCInt.equal 128 in \
let l = topo_sort ~eq:CCInt.equal ~rev:true ~tbl ~graph:divisors_graph (Iter.return 42) in \ let l = topo_sort ~eq:CCInt.equal ~rev:true ~tbl ~graph:divisors_graph (Iter.return 42) in \
List.for_all (fun (i,j) -> \ List.for_all (fun (i,j) -> \
let idx_i = CCList.find_idx ((=)i) l |> CCOpt.get_exn |> fst in \ let idx_i = CCList.find_idx ((=)i) l |> CCOption.get_exn |> fst in \
let idx_j = CCList.find_idx ((=)j) l |> CCOpt.get_exn |> fst in \ let idx_j = CCList.find_idx ((=)j) l |> CCOption.get_exn |> fst in \
idx_i > idx_j) \ idx_i > idx_j) \
[ 42, 21; 14, 2; 3, 1; 21, 7; 42, 3] [ 42, 21; 14, 2; 3, 1; 21, 7; 42, 3]
*) *)

View file

@ -499,7 +499,7 @@ let rec filter_map f m = match m with
(*$QR (*$QR
Q.(pair (fun2 Observable.int Observable.int @@ option bool) (small_list (pair int int))) (fun (f,l) -> Q.(pair (fun2 Observable.int Observable.int @@ option bool) (small_list (pair int int))) (fun (f,l) ->
let QCheck.Fun(_,f) = f in let QCheck.Fun(_,f) = f in
_list_uniq (CCList.filter_map (fun (x,y) -> CCOpt.map (CCPair.make x) @@ f x y) l) = _list_uniq (CCList.filter_map (fun (x,y) -> CCOption.map (CCPair.make x) @@ f x y) l) =
(_list_uniq @@ to_list @@ filter_map f @@ of_list l) (_list_uniq @@ to_list @@ filter_map f @@ of_list l)
) )
*) *)

View file

@ -534,7 +534,7 @@ module MakeFull(K : KEY) : S with type key = K.t = struct
(*$R (*$R
let m1 = M.of_list [1, 1; 2, 2; 4, 4] in let m1 = M.of_list [1, 1; 2, 2; 4, 4] in
let m2 = M.of_list [1, 1; 3, 3; 4, 4; 7, 7] in let m2 = M.of_list [1, 1; 3, 3; 4, 4; 7, 7] in
let m = M.merge ~f:(fun k -> CCOpt.map2 (+)) m1 m2 in let m = M.merge ~f:(fun k -> CCOption.map2 (+)) m1 m2 in
assert_bool "balanced" (M.balanced m); assert_bool "balanced" (M.balanced m);
assert_equal assert_equal
~cmp:(CCList.equal (CCPair.equal CCInt.equal CCInt.equal)) ~cmp:(CCList.equal (CCPair.equal CCInt.equal CCInt.equal))

View file

@ -69,7 +69,7 @@ let focused = function
(*$Q (*$Q
zip_gen (fun g -> \ zip_gen (fun g -> \
is_focused g = (focused g |> CCOpt.is_some)) is_focused g = (focused g |> CCOption.is_some))
*) *)
let focused_exn = function let focused_exn = function