include module type of Stdlib.Option

(** [eliminate none_handler some_handler o] is [some_handler v] if [o] is
    [Some v], and [none_handler ()] otherwise. *)
val eliminate : (unit -> 'b) -> ('a -> 'b) -> 'a t -> 'b

(** [get_or_else f o] is [f ()] if [o] is [None] and [v] if [o] is [Some v]. *)
val get_or_else : (unit -> 'a) -> 'a t -> 'a

(** [of_bool b] is [Some ()] if [b] is [true], and [None] otherwise.

    When used with other monadic operations, this is (a specialized) [guard]
    function from Haskell, which allows to abort a monadic computation on
    account of a boolean check. *)
val of_bool : bool -> unit t

(** [from_predicate p a] is [Some a] if [p a], and [None] otherwise. *)
val from_predicate : ('a -> bool) -> 'a -> 'a t

(** [lazy_alt a1 a2] is [a1] if it is not [lazy None], and [a2] otherwise. *)
val lazy_alt : 'a t Lazy.t -> 'a t Lazy.t -> 'a t Lazy.t

(** Infix operator alias of {!lazy_alt}. *)
val ( <||> ) : 'a t Lazy.t -> 'a t Lazy.t -> 'a t Lazy.t

val void : 'a t -> unit t

(** Specialized effectful eliminator for option types. *)
val when_some : 'a t -> ('a -> unit) -> unit

(** Prints an option by doing nothing if it is [None]; else it uses the given
    printer. *)
val print :
  (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit

(** Prints an option by showing ["None"] or ["Some (X)"] where ["X"] is
    generated by the given formatting function. *)
val pp : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit

(** {1 Instances} *)

include Monad.MONAD with type 'a t := 'a t

include Functor.FUNCTOR with type 'a t := 'a t

include Apply.APPLY with type 'a t := 'a t

include Alternative.ALTERNATIVE with type 'a t := 'a t

(** Functor for an instance of {!Eq.EQ} over option values using {!equal}. *)
module MakeEq (E : Eq.EQ) : Eq.EQ with type t = E.t t

(** Functor for an instance of {!Ord.ORD} over option values using
    {!compare}. *)
module MakeOrd (O : Ord.ORD) : Ord.ORD with type t = O.t t

(** Functor for an instance of {!Show.SHOW} over option values using {!pp}. *)
module MakeShow (S : Show.SHOW) : Show.SHOW with type t = S.t t
