diff --git a/src/core/CCFun.ml b/src/core/CCFun.ml index 65c9a5d5..d70c00b7 100644 --- a/src/core/CCFun.ml +++ b/src/core/CCFun.ml @@ -77,7 +77,11 @@ struct type 'a t = X.t -> 'a let[@inline] return x _ = x + let[@inline] k_compose f g = + (fun x -> f x |> flat_map g) let[@inline] ( >|= ) f g x = g (f x) let[@inline] ( >>= ) f g x = g (f x) x + let[@inline] ( >=> ) = k_compose + let[@inline] ( <=< ) = flip k_compose end [@@inline] diff --git a/src/core/CCFun.mli b/src/core/CCFun.mli index 1557f780..2cd4774e 100644 --- a/src/core/CCFun.mli +++ b/src/core/CCFun.mli @@ -105,8 +105,18 @@ end) : sig val return : 'a -> 'a t (** Monadic [return]. *) + val k_compose : ('a -> 'b t) -> ('b -> 'c t) -> ('a -> 'c t) + (** Kleisli composition. Monadic equivalent of [compose]. *) + val ( >|= ) : 'a t -> ('a -> 'b) -> 'b t + (** Mondaic [map]. *) val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t (** Monadic [bind]. *) + + val ( >=> ) : ('a -> 'b t) -> ('b -> 'c t) -> ('a -> 'c t) + (** Monadic [k_compose]. *) + + val ( <=< ) : ('b -> 'c t) -> ('a -> 'b t) -> ('a -> 'c t) + (** Reverse monadic [k_compose]. *) end diff --git a/src/core/CCOption.ml b/src/core/CCOption.ml index 10bd4239..6bc1ddde 100644 --- a/src/core/CCOption.ml +++ b/src/core/CCOption.ml @@ -55,6 +55,11 @@ let[@inline] bind o f = flat_map f o let ( >>= ) = bind let pure x = Some x +let k_compose f g = + (fun x -> f x |> flat_map g) +let ( >=> ) = k_compose +let ( <=< ) f g = (>=>) g f + let ( <*> ) f x = match f, x with | None, _ | _, None -> None @@ -190,6 +195,10 @@ module Infix = struct | _ -> None let ( and* ) = ( and+ ) + + let ( >=> ) = ( >=> ) + + let ( <=< ) = ( <=< ) end include Infix diff --git a/src/core/CCOption.mli b/src/core/CCOption.mli index 06ad03d9..e1f8d30a 100644 --- a/src/core/CCOption.mli +++ b/src/core/CCOption.mli @@ -58,6 +58,9 @@ val bind : 'a t -> ('a -> 'b t) -> 'b t Monadic bind. @since 3.0 *) +val k_compose : ('a -> 'b t) -> ('b -> 'c t) -> ('a -> 'c t) +(** Kleisli composition. Monadic equivalent of CCFun.compose *) + 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]. *) @@ -179,6 +182,11 @@ module Infix : sig val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t val ( and* ) : 'a t -> 'b t -> ('a * 'b) t + + val ( >=> ) : ('a -> 'b t) -> ('b -> 'c t) -> ('a -> 'c t) + (** Monadic [k_compose]. *) + val ( <=< ) : ('b -> 'c t) -> ('a -> 'b t) -> ('a -> 'c t) + (** Reverse monadic [k_compose]. *) end include module type of Infix diff --git a/src/core/CCResult.ml b/src/core/CCResult.ml index 9acb529b..4f743600 100644 --- a/src/core/CCResult.ml +++ b/src/core/CCResult.ml @@ -125,6 +125,12 @@ let flat_map f e = | Ok x -> f x | Error s -> Error s +let k_compose f g = + (fun x -> flat_map g @@ f x) + +let ( >=> ) = k_compose +let ( <=< ) f g = ( >=> ) g f + let equal ~err eq a b = match a, b with | Ok x, Ok y -> eq x y @@ -275,6 +281,9 @@ module Infix = struct | _, Error e -> Error e let ( and* ) = ( and+ ) + + let ( >=> ) = ( >=> ) + let ( <=< ) = ( <=< ) end include Infix diff --git a/src/core/CCResult.mli b/src/core/CCResult.mli index 50b7fb68..171bc273 100644 --- a/src/core/CCResult.mli +++ b/src/core/CCResult.mli @@ -113,6 +113,10 @@ val catch : ('a, 'err) t -> ok:('a -> 'b) -> err:('err -> 'b) -> 'b the value of [e]. *) val flat_map : ('a -> ('b, 'err) t) -> ('a, 'err) t -> ('b, 'err) t + +val k_compose : ('a -> ('b, 'err) t) -> ('b -> ('c, 'err) t) -> ('a -> ('c, 'err) t) +(** Kleisli composition. Monadic equivalent of CCFun.compose *) + val equal : err:'err equal -> 'a equal -> ('a, 'err) t equal val compare : err:'err ord -> 'a ord -> ('a, 'err) t ord @@ -199,6 +203,11 @@ module Infix : sig val ( and* ) : ('a, 'e) t -> ('b, 'e) t -> ('a * 'b, 'e) t (** @since 2.8 *) + + val ( >=> ) : ('a -> ('b, 'err) t) -> ('b -> ('c, 'err) t) -> ('a -> ('c, 'err) t) + (** Monadic [k_compose]. *) + val ( <=< ) : ('b -> ('c, 'err) t) -> ('a -> ('b, 'err) t) -> ('a -> ('c, 'err) t) + (** Reverse monadic [k_compose]. *) end include module type of Infix