let ( let* ) o f = match o with Ok v -> f v | Error _ as e -> e let ( let+ ) o f = match o with Ok v -> Ok (f v) | Error _ as e -> e (* TODO use polymorphic variant for errors *) let unwrap_err_msg o = match o with Error (`Msg e) -> Error e | Ok v -> Ok v let unwrap_err_caqti o = match o with Error err -> Fmt.error "%a" Caqti_error.pp err | Ok v -> Ok v let list_iter f l = let err = ref None in try List.iter (fun v -> match f v with | Error _e as e -> err := Some e; raise Exit | Ok () -> ()) l; Ok () with Exit -> ( match !err with None -> assert false | Some v -> v) let list_map f l = let err = ref None in try Ok (List.map (fun v -> match f v with | Error _e as e -> err := Some e; raise Exit | Ok v -> v) l) with Exit -> ( match !err with None -> assert false | Some v -> v) let list_filter_map f l = let err = ref None in try Ok (List.filter_map (fun v -> match f v with | Error _e as e -> err := Some e; raise Exit | Ok v -> v) l) with Exit -> ( match !err with None -> assert false | Some v -> v) let list_fold_left f acc l = List.fold_left (fun acc v -> let* acc = acc in f acc v) (Ok acc) l let opt_list l = match (List.for_all Option.is_none l, List.for_all Option.is_some l) with | _, true -> let l = List.map Option.get l in Ok (Some l) | true, _ -> Ok None | _, _ -> Error ()