type ('a, 'e) res = [ | `Ok of 'a | `Error of 'e ]
type 'a m = ('a, exn) res
let return r = `Ok r
let fail e = `Error e
let error e = `Error e
let bind f m = match m with | `Ok a -> f a | (`Error _ as e) -> e
let ( >>= ) m f = bind f m
let bind_rev = ( >>= )
let catch func handler =
match func () with | (`Ok _ as r) -> r | `Error e -> handler e
let wrap1 f a = try `Ok (f a) with | e -> `Error e
let wrap2 f a b = try `Ok (f a b) with | e -> `Error e
let wrap3 f a b c = try `Ok (f a b c) with | e -> `Error e
let wrap4 f a b c d = try `Ok (f a b c d) with | e -> `Error e
let wrap5 f a b c d e = try `Ok (f a b c d e) with | e' -> `Error e'
let catch_exn func = try func () with | e -> fail e
let catch_all f handler = catch (fun () -> catch_exn f) handler
let exn_res r = match r with | `Ok x -> x | `Error e -> raise e
let map_err f r = match r with | (`Ok _ as r) -> r | `Error e -> `Error (f e)
let res_opterr oe = match oe with | None -> `Ok () | Some e -> `Error e
let res_optval ov = match ov with | None -> `Error () | Some v -> `Ok v
open Am_Ops
let res_exn func = catch_exn (return % func)
exception Foldres_exit
let (foldres_of_fold :
(('a -> 'i -> 'a) -> 'a -> 'v -> 'a) ->
('a -> 'i -> ('a, 'e) res) -> 'a -> 'v -> ('a, 'e) res) =
fun fold f init v ->
let opt_err = ref None in
let new_f a v =
match f a v with
| `Ok new_a -> new_a
| `Error e -> (opt_err := Some e; raise Foldres_exit)
in
try `Ok (fold new_f init v)
with
| Foldres_exit ->
(match !opt_err with | None -> assert false | Some e -> `Error e)
let rprintf fmt =
Printf.ksprintf
(fun str -> try return & (output_string stdout str) with | e -> `Error e)
fmt
let reprintf fmt =
Printf.ksprintf
(fun str ->
try return & (output_string stderr str; flush stderr)
with | e -> `Error e)
fmt
let wrap_with1 with1 a f = res_exn & (fun () -> with1 a (exn_res % f))
let wrap_with3 with3 a b c f =
res_exn & (fun () -> with3 a b c (exn_res % f))
let list_map_all func lst =
let rec inner rev_acc lst =
match lst with
| [] -> return & (List.rev rev_acc)
| h :: t ->
(match func h with
| `Ok x -> inner (x :: rev_acc) t
| `Error e -> `Error ((h, e)))
in inner [] lst
let array_map_all func arr =
let lst = Array.to_list arr
in
(list_map_all func lst) >>=
(fun res_lst -> return & (Array.of_list res_lst))
let list_fold_left_all func init lst =
let rec inner init lst =
match lst with
| [] -> return init
| h :: t ->
(match func init h with
| `Ok x -> inner x t
| `Error e -> `Error ((h, t, init, e)))
in inner init lst
let list_iter_all func lst =
catch
(fun () ->
list_fold_left_all (fun () x -> (func x : (unit, _) res)) () lst)
(fun (h, t, (), e) -> fail (h, t, e))
let repeat n f a =
let rec inner made a =
if made >= n
then `Ok a
else
(match f a with
| `Ok a -> inner (made + 1) a
| `Error e -> `Error ((e, made)))
in inner 0 a