CCError: retry and choose combinators

This commit is contained in:
Simon Cruanes 2014-07-02 13:22:21 +02:00
parent 94ff411f9f
commit a64d7602a3
2 changed files with 52 additions and 0 deletions

View file

@ -129,6 +129,37 @@ let fold_seq f acc seq =
let fold_l f acc l = fold_seq f acc (fun k -> List.iter k l)
(** {2 Misc} *)
let choose l =
let rec _find = function
| [] -> raise Not_found
| ((`Ok _) as res) :: _ -> res
| (`Error _) :: l' -> _find l'
in
try _find l
with Not_found ->
let buf = Buffer.create 32 in
(* print errors on the buffer *)
let rec print buf l = match l with
| `Ok _ :: _ -> assert false
| (`Error x)::((y::xs) as l) ->
Buffer.add_string buf x;
Buffer.add_string buf ", ";
print buf l
| `Error x::[] -> Buffer.add_string buf x
| [] -> ()
in
Printf.bprintf buf "CCError.choice failed: [%a]" print l;
fail (Buffer.contents buf)
let rec retry n f = match n with
| 0 -> fail "retry failed"
| _ ->
match f () with
| `Ok _ as res -> res
| `Error _ -> retry (n-1) f
(** {2 Monadic Operations} *)
module type MONAD = sig
@ -149,6 +180,14 @@ module Traverse(M : MONAD) = struct
let fold_m f acc e = match e with
| `Error s -> M.return acc
| `Ok x -> f acc x >>= fun y -> M.return y
let rec retry_m n f = match n with
| 0 -> M.return (fail "retry failed")
| _ ->
let x = f () in
x >>= function
| `Ok _ -> x
| `Error _ -> retry_m (n-1) f
end
(** {2 Conversions} *)

View file

@ -89,6 +89,17 @@ val fold_l : ('b -> 'a -> 'b t) -> 'b -> 'a list -> 'b t
val fold_seq : ('b -> 'a -> 'b t) -> 'b -> 'a sequence -> 'b t
(** {2 Misc} *)
val choose : 'a t list -> 'a t
(** [choose l] selects a member of [l] that is a [`Ok _] value,
or returns [`Error msg] otherwise, where [msg] is obtained by
combining the error messages of all elements of [l] *)
val retry : int -> (unit -> 'a t) -> 'a t
(** [retry n f] calls [f] at most [n] times, returning the first result
of [f ()] that doesn't fail. If [f] fails [n] times, [retry n f] fails. *)
(** {2 Monadic Operations} *)
module type MONAD = sig
type 'a t
@ -102,6 +113,8 @@ module Traverse(M : MONAD) : sig
val fold_m : ('b -> 'a -> 'b M.t) -> 'b -> 'a t -> 'b M.t
val map_m : ('a -> 'b M.t) -> 'a t -> 'b t M.t
val retry_m : int -> (unit -> 'a t M.t) -> 'a t M.t
end
(** {2 Conversions} *)