Skip to content

Commit

Permalink
Make BatResult a superset of OCaml new Result module.
Browse files Browse the repository at this point in the history
Breaks compatibility with previous versions by renaming our Result.Bad into
OCaml new Result.Error.

Closes ocaml-batteries-team#839
  • Loading branch information
rixed committed Sep 27, 2019
1 parent 9d3ab53 commit 43f3400
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 85 deletions.
8 changes: 4 additions & 4 deletions src/batInnerPervasives.mlv
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ let unique () =

type ('a, 'b) result =
| Ok of 'a
| Bad of 'b
| Error of 'b

(* Ideas taken from Nicholas Pouillard's my_std.ml in ocamlbuild/ *)
let ignore_ok = function
Ok _ -> ()
| Bad ex -> raise ex
| Error ex -> raise ex

let ok = function
Ok v -> v
| Bad ex -> raise ex
| Error ex -> raise ex

let wrap f x = try Ok (f x) with ex -> Bad ex
let wrap f x = try Ok (f x) with ex -> Error ex

let forever f x = ignore (while true do f x done)

Expand Down
2 changes: 1 addition & 1 deletion src/batParserCo.ml
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ let lookahead p e = match apply p e with
| Failure _ as result -> result

let interpret_result = function
| Setback f | Failure f -> BatInnerPervasives.Bad f
| Setback f | Failure f -> BatInnerPervasives.Error f
| Success (r, _) | Backtrack (r, _, _) -> BatInnerPervasives.Ok r

let suspend : ('a, 'b, 'c) t -> ('a, (unit -> ('b, 'c report) BatInnerPervasives.result), 'c) t = fun s e ->
Expand Down
2 changes: 1 addition & 1 deletion src/batParserCo.mli
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ val suspend : ('a, 'b, 'c) t -> ('a, (unit -> ('b, 'c report) BatPervasives.resu
val run: ('a, 'b, 'c) t -> ('a, 'c) Source.t -> ('b, 'c report) BatPervasives.result
(**[run p s] executes parser [p] on source [s]. In case of
success, returns [Ok v], where [v] is the return value of [p].
In case of failure, returns [Bad f], with [f] containing
In case of failure, returns [Error f], with [f] containing
details on the parsing error.*)


Expand Down
14 changes: 7 additions & 7 deletions src/batPervasives.mliv
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ val print : ?first:string -> ?last:string -> ?sep:string -> ('a BatInnerIO.outp
(** This type represents the outcome of a function which has the
possibility of failure. Normal results of type ['a] are marked
with [Ok], while failure values of type ['b] are marked with
[Bad].
[Error].

This is intended to be a safer alternative to functions raising
exceptions to signal failure. It is safer in that the possibility
Expand All @@ -848,25 +848,25 @@ val print : ?first:string -> ?last:string -> ?sep:string -> ('a BatInnerIO.outp

For more functions related to this type, see the {!BatResult} module.
*)
type ('a, 'b) result = ('a, 'b) BatInnerPervasives.result =
type ('a, 'e) result = ('a, 'e) BatInnerPervasives.result =
| Ok of 'a
| Bad of 'b
| Error of 'e
(** The result of a computation - either an [Ok] with the normal
result or a [Bad] with some value (often an exception) containing
result or a [Error] with some value (often an exception) containing
failure information*)

val ignore_ok : ('a, exn) result -> unit
(** [ignore_ok (f x)] ignores the result of [f x] if it's ok, but
throws the exception contained if [Bad] is returned. *)
throws the exception contained if [Error] is returned. *)

val ok : ('a, exn) result -> 'a
(** [f x |> ok] unwraps the [Ok] result of [f x] and returns it, or
throws the exception contained if [Bad] is returned. *)
throws the exception contained if [Error] is returned. *)

val wrap : ('a -> 'b) -> 'a -> ('b, exn) result
(** [wrap f x] wraps a function that would normally throw an exception
on failure such that it now returns a result with either the [Ok]
return value or the [Bad] exception. *)
return value or the [Error] exception. *)


(**
Expand Down
89 changes: 65 additions & 24 deletions src/batResult.ml
Original file line number Diff line number Diff line change
@@ -1,66 +1,107 @@

type ('a, 'b) t = ('a, 'b) BatPervasives.result =
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* The OCaml programmers *)
(* *)
(* Copyright 2018 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)

type ('a, 'e) t = ('a, 'e) BatPervasives.result =
| Ok of 'a
| Bad of 'b

let catch f x = try Ok (f x) with e -> Bad e
let catch2 f x y = try Ok (f x y) with e -> Bad e
let catch3 f x y z = try Ok (f x y z) with e -> Bad e
| Error of 'e

let ok v = Ok v
let error e = Error e
let value r ~default = match r with Ok v -> v | Error _ -> default
let get_ok = function Ok v -> v | Error _ -> invalid_arg "result is Error _"
let get_error = function Error e -> e | Ok _ -> invalid_arg "result is Ok _"
let bind r f = match r with Ok v -> f v | Error _ as e -> e
let join = function Ok r -> r | Error _ as e -> e
let map_error f = function Error e -> Error (f e) | Ok _ as v -> v
let fold ~ok ~error = function Ok v -> ok v | Error e -> error e
let iter f = function Ok v -> f v | Error _ -> ()
let iter_error f = function Error e -> f e | Ok _ -> ()
let is_error = function Error _ -> true | Ok _ -> false

let equal ~ok ~error r0 r1 = match r0, r1 with
| Ok v0, Ok v1 -> ok v0 v1
| Error e0, Error e1 -> error e0 e1
| _, _ -> false

let compare ~ok ~error r0 r1 = match r0, r1 with
| Ok v0, Ok v1 -> ok v0 v1
| Error e0, Error e1 -> error e0 e1
| Ok _, Error _ -> -1
| Error _, Ok _ -> 1

let to_list = function Ok v -> [v] | Error _ -> []
let to_seq = function Ok v -> BatSeq.(cons v nil) | Error _ -> BatSeq.nil

let catch f x = try Ok (f x) with e -> Error e
let catch2 f x y = try Ok (f x y) with e -> Error e
let catch3 f x y z = try Ok (f x y z) with e -> Error e

let of_option = function
| Some x -> Ok x
| None -> Bad ()
| None -> Error ()

let to_option = function
| Ok x -> Some x
| Bad _-> None
| Error _-> None

let default def = function
| Ok x -> x
| Bad _ -> def
| Error _ -> def

let map f = function
| Bad e -> Bad e
| Error e -> Error e
| Ok v -> Ok (f v)
(*$T map
map succ (Bad (-1)) = (Bad (-1))
map succ (Bad 0) = (Bad 0)
map succ (Error (-1)) = (Error (-1))
map succ (Error 0) = (Error 0)
map succ (Ok 3) = (Ok 4)
*)

let map_both f g = function
| Bad e -> Bad (g e)
| Error e -> Error (g e)
| Ok v -> Ok (f v)
(*$T map_both
map_both succ pred (Bad (-1)) = (Bad (-2))
map_both succ pred (Bad 0) = (Bad (-1))
map_both succ pred (Bad 1) = (Bad 0)
map_both succ pred (Error (-1)) = (Error (-2))
map_both succ pred (Error 0) = (Error (-1))
map_both succ pred (Error 1) = (Error 0)
map_both succ pred (Ok (-1)) = (Ok 0)
map_both succ pred (Ok 0) = (Ok 1)
map_both succ pred (Ok 1) = (Ok 2)
*)

let map_default def f = function
| Ok x -> f x
| Bad _ -> def
| Error _ -> def

let is_ok = function Ok _ -> true | Bad _ -> false
let is_ok = function Ok _ -> true | Error _ -> false

let is_bad = function Bad _ -> true | Ok _ -> false
let is_bad = function Error _ -> true | Ok _ -> false

let is_exn e = function Bad exn -> exn = e | Ok _ -> false
let is_exn e = function Error exn -> exn = e | Ok _ -> false

let get = function Ok x -> x | Bad e -> raise e
let get = function Ok x -> x | Error e -> raise e

let print print_val oc = function
| Ok x -> BatPrintf.fprintf oc "Ok(%a)" print_val x
| Bad e -> BatPrintf.fprintf oc "Bad(%a)" BatPrintexc.print e
| Error e -> BatPrintf.fprintf oc "Error(%a)" BatPrintexc.print e


module Monad = struct
let bind m k = match m with
| Ok x -> k x
| Bad _ as e -> e
| Error _ as e -> e

let return x = Ok x

Expand Down
Loading

0 comments on commit 43f3400

Please sign in to comment.