This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,6 @@
_b0
_build
tmp
*.native
*.byte
*.install

View file

@ -0,0 +1,4 @@
PKG b0.kit
S src
S test
B _build/**

View file

@ -0,0 +1 @@
strict_with=always,match_clause=4,strict_else=never

View file

@ -0,0 +1,59 @@
open B0_kit.V000
open B00_std
open Result.Syntax
(* OCaml library names *)
let compiler_libs_toplevel = B0_ocaml.libname "compiler-libs.toplevel"
let rresult = B0_ocaml.libname "rresult"
let rresult_top = B0_ocaml.libname "rresult.top"
(* Libraries *)
let result_lib =
let srcs =
Fpath.[ `File (v "src/rresult.mli"); `File (v "src/rresult.ml"); ]
in
let requires = [] in
B0_ocaml.lib rresult ~doc:"The rresult library" ~srcs ~requires
let rresult_top =
let srcs = Fpath.[ `File (v "src/rresult_top.ml") ] in
let requires = [compiler_libs_toplevel] in
B0_ocaml.lib rresult_top ~doc:"The rresult.top library" ~srcs ~requires
(* Tests *)
let test =
let srcs = Fpath.[`File (v "test/test.ml")] in
let meta = B0_meta.(empty |> tag test) in
let requires = [ rresult ] in
B0_ocaml.exe "test" ~doc:"Test suite" ~srcs ~meta ~requires
(* Packs *)
let default =
let meta =
let open B0_meta in
empty
|> tag B0_opam.tag
|> add authors ["The rresult programmers"]
|> add maintainers ["Daniel Bünzli <daniel.buenzl i@erratique.ch>"]
|> add homepage "https://erratique.ch/software/rresult"
|> add online_doc "https://erratique.ch/software/rresult/doc/Rresult"
|> add licenses ["ISC"]
|> add repo "git+https://erratique.ch/repos/rresult.git"
|> add issues "https://github.com/dbuenzli/rresult/issues"
|> add description_tags ["result"; "error"; "org:erratique"]
|> add B0_opam.Meta.build
{|[["ocaml" "pkg/pkg.ml" "build" "--dev-pkg" "%{dev}%"]]|}
|> add B0_opam.Meta.depends
[ "ocaml", {|>= "4.08.0"|};
"ocamlfind", {|build|};
"ocamlbuild", {|build|};
"topkg", {|build & >= "1.0.3"|};
]
in
B0_pack.v "default" ~doc:"rresult package" ~meta ~locked:true @@
B0_unit.list ()

View file

View file

@ -0,0 +1,53 @@
v0.7.0 2021-10-04 Zagreb
------------------------
* Require OCaml >= 4.08. This drops the dependency on the `result`
compatibility package.
* Users are encouraged to move the the `Stdlib.Result` module
available in OCaml 4.08.
v0.6.0 2018-10-07 Zagreb
------------------------
* Add `R.failwith_error_msg`.
v0.5.0 2016-09-03 Zagreb
------------------------
* `R.[k]ignore_error` use a thunk for the `~use` argument. This is an
incompatible change. Simply wrap occurences of `~use:e` with
`~use:(fun _ -> e)`.
v0.4.0 2016-05-23 La Forclaz (VS)
---------------------------------
* Build depend on topkg.
* Relicense from BSD3 to ISC.
* `R.pp` remove the `pp_` prefix from the labels and do not print the
constructors names, use to the newly introduced `R.dump` for this.
This follows the conventions of `Fmt`.
v0.3.0 2015-11-30 Cambridge (UK)
--------------------------------
* Use the type provided by the `Result` compatibility library. Opening
`Rresult` still gives you both unprefixed variant constructors and infix
operators.
* Remove the `R.{int,nativeint,int32,int64,float,bool}_of_string` functions.
They do not belong here.
* `R.map`, swap argument order. Thanks to Gabriel Radanne for suggesting.
* Fix `R.bind` which had a more restrictive type than `>>=`. Thanks to
Hezekiah M. Carty for the patch.
v0.2.0 2015-05-20 La Forclaz (VS)
---------------------------------
* The `Rresult_infix` module no longer exists. Open directly `Rresult`
for using the library.
v0.1.0 2015-03-19 La Forclaz (VS)
---------------------------------
First release.

View file

@ -0,0 +1,13 @@
Copyright (c) 2014 The rresult programmers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -0,0 +1,44 @@
Rresult — Result value combinators for OCaml
-------------------------------------------------------------------------------
v0.7.0+dune
Rresult is an OCaml module for handling computation results and errors
in an explicit and declarative manner, without resorting to
exceptions. It defines combinators to operate on the `result` type
available from OCaml 4.03 in the standard library.
OCaml 4.08 provides the `Stdlib.Result` module which you should prefer
to Rresult.
Rresult is distributed under the ISC license.
Home page: http://erratique.ch/software/rresult
Contact: Daniel Bünzli `<daniel.buenzl i@erratique.ch>`
## Installation
Rresult can be installed with `opam`:
opam install rresult
If you don't use `opam` consult the [`opam`](opam) file for build
instructions.
## Documentation
The documentation and API reference is automatically generated by
`ocamldoc` from the interfaces. It can be consulted [online][doc]
[doc]: http://erratique.ch/software/rresult/doc/
## Sample programs
If you installed Rresult with `opam` sample programs are located in
the directory `opam config var rresult:doc`.
In the distribution sample programs and tests are located in the
[`test`](test) directory of the distribution. They can be built and run
with:
topkg build --tests true && topkg test

View file

@ -0,0 +1,5 @@
true : bin_annot, safe_string
<_b0> : -traverse
<src> : include
<src/rresult_top*> : package(compiler-libs.toplevel)
<test> : include

View file

@ -0,0 +1,5 @@
{0 Rresult {%html: <span class="version">v0.7.0+dune</span>%}}
{!modules:
Rresult
}

View file

@ -0,0 +1,3 @@
(lang dune 1.0)
(name rresult)
(version v0.7.0+dune)

View file

@ -0,0 +1,17 @@
description = "Result value combinators for OCaml"
version = "0.7.0+dune"
requires = ""
archive(byte) = "rresult.cma"
archive(native) = "rresult.cmxa"
plugin(byte) = "rresult.cma"
plugin(native) = "rresult.cmxs"
package "top" (
description = "Rresult toplevel support"
version = "0.7.0+dune"
requires = "rresult"
archive(byte) = "rresult_top.cma"
archive(native) = "rresult_top.cmxa"
plugin(byte) = "rresult_top.cma"
plugin(native) = "rresult_top.cmxs"
)

View file

@ -0,0 +1,12 @@
#!/usr/bin/env ocaml
#use "topfind";;
#require "topkg"
open Topkg
let () =
Pkg.describe "rresult" @@ fun c ->
Ok [ Pkg.mllib ~api:["Rresult"] "src/rresult.mllib";
Pkg.mllib ~api:[] "src/rresult_top.mllib";
Pkg.lib "src/rresult_top_init.ml";
Pkg.doc "doc/index.mld" ~dst:"odoc-pages/index.mld";
Pkg.test "test/test"; ]

View file

@ -0,0 +1,29 @@
version: "0.7.0+dune"
opam-version: "2.0"
name: "rresult"
synopsis: """Result value combinators for OCaml"""
maintainer: ["Daniel Bünzli <daniel.buenzl i@erratique.ch>"]
authors: ["The rresult programmers"]
homepage: "https://github.com/dune-universe/rresult"
dev-repo: "git+https://github.com/dune-universe/rresult.git"
bug-reports: "https://github.com/dbuenzli/rresult/issues"
license: ["ISC"]
tags: ["result" "error" "org:erratique"]
depends: [
"dune"
"ocaml" {>= "4.08.0"}
]
build: [ "dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} ]
description: """
Rresult is an OCaml module for handling computation results and errors
in an explicit and declarative manner, without resorting to
exceptions. It defines combinators to operate on the `result` type
available from OCaml 4.03 in the standard library.
OCaml 4.08 provides the `Stdlib.Result` module which you should prefer
to Rresult.
Rresult is distributed under the ISC license.
Home page: http://erratique.ch/software/rresult
Contact: Daniel Bünzli `<daniel.buenzl i@erratique.ch>`"""

View file

@ -0,0 +1,12 @@
(library
(name rresult)
(public_name rresult)
(modules rresult)
(wrapped false))
(library
(name rresult_top)
(public_name rresult.top)
(libraries compiler-libs.toplevel rresult)
(modules rresult_top)
(wrapped false))

View file

@ -0,0 +1,156 @@
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
---------------------------------------------------------------------------*)
type ('a, 'b) result = ('a, 'b) Stdlib.result = Ok of 'a | Error of 'b
module R = struct
let err_error = "result value is (Error _)"
let err_ok = "result value is (Ok _)"
(* Results *)
type ('a, 'b) t = ('a, 'b) result
let ok v = Ok v
let error e = Error e
let get_ok = function Ok v -> v | Error _ -> invalid_arg err_error
let get_error = function Error e -> e | Ok _ -> invalid_arg err_ok
let reword_error reword = function
| Ok _ as r -> r
| Error e -> Error (reword e)
let return = ok
let fail = error
(* Composing results *)
let bind v f = match v with Ok v -> f v | Error _ as e -> e
let map f v = match v with Ok v -> Ok (f v) | Error _ as e -> e
let join r = match r with Ok v -> v | Error _ as e -> e
let ( >>= ) = bind
let ( >>| ) v f = match v with Ok v -> Ok (f v) | Error _ as e -> e
module Infix = struct
let ( >>= ) = ( >>= )
let ( >>| ) = ( >>| )
end
(* Error messages *)
let pp_lines ppf s = (* hints new lines *)
let left = ref 0 and right = ref 0 and len = String.length s in
let flush () =
Format.pp_print_string ppf (String.sub s !left (!right - !left));
incr right; left := !right;
in
while (!right <> len) do
if s.[!right] = '\n' then (flush (); Format.pp_force_newline ppf ()) else
incr right;
done;
if !left <> len then flush ()
type msg = [ `Msg of string ]
let msg s = `Msg s
let msgf fmt =
let kmsg _ = `Msg (Format.flush_str_formatter ()) in
Format.kfprintf kmsg Format.str_formatter fmt
let pp_msg ppf (`Msg msg) = pp_lines ppf msg
let error_msg s = Error (`Msg s)
let error_msgf fmt =
let kerr _ = Error (`Msg (Format.flush_str_formatter ())) in
Format.kfprintf kerr Format.str_formatter fmt
let reword_error_msg ?(replace = false) reword = function
| Ok _ as r -> r
| Error (`Msg e) ->
let (`Msg e' as v) = reword e in
if replace then Error v else error_msgf "%s\n%s" e e'
let error_to_msg ~pp_error = function
| Ok _ as r -> r
| Error e -> error_msgf "%a" pp_error e
let error_msg_to_invalid_arg = function
| Ok v -> v
| Error (`Msg m) -> invalid_arg m
let open_error_msg = function Ok _ as r -> r | Error (`Msg _) as r -> r
let failwith_error_msg = function Ok v -> v | Error (`Msg m) -> failwith m
(* Trapping unexpected exceptions *)
type exn_trap = [ `Exn_trap of exn * Printexc.raw_backtrace ]
let pp_exn_trap ppf (`Exn_trap (exn, bt)) =
Format.fprintf ppf "%s@\n" (Printexc.to_string exn);
pp_lines ppf (Printexc.raw_backtrace_to_string bt)
let trap_exn f v = try Ok (f v) with
| e ->
let bt = Printexc.get_raw_backtrace () in
Error (`Exn_trap (e, bt))
let error_exn_trap_to_msg = function
| Ok _ as r -> r
| Error trap ->
error_msgf "Unexpected exception:@\n%a" pp_exn_trap trap
let open_error_exn_trap = function
| Ok _ as r -> r | Error (`Exn_trap _) as r -> r
(* Pretty-printing *)
let pp ~ok ~error ppf = function Ok v -> ok ppf v | Error e -> error ppf e
let dump ~ok ~error ppf = function
| Ok v -> Format.fprintf ppf "@[<2>Ok@ @[%a@]@]" ok v
| Error e -> Format.fprintf ppf "@[<2>Error@ @[%a@]@]" error e
(* Predicates *)
let is_ok = function Ok _ -> true | Error _ -> false
let is_error = function Ok _ -> false | Error _ -> true
let equal ~ok ~error r r' = match r, r' with
| Ok v, Ok v' -> ok v v'
| Error e, Error e' -> error e e'
| _ -> false
let compare ~ok ~error r r' = match r, r' with
| Ok v, Ok v' -> ok v v'
| Error v, Error v' -> error v v'
| Ok _, Error _ -> -1
| Error _, Ok _ -> 1
(* Converting *)
let to_option = function Ok v -> Some v | Error e -> None
let of_option ~none = function None -> none () | Some v -> Ok v
let to_presult = function Ok v -> `Ok v | Error e -> `Error e
let of_presult = function `Ok v -> Ok v | `Error e -> Error e
(* Ignoring errors *)
let ignore_error ~use = function Ok v -> v | Error e -> use e
let kignore_error ~use = function Ok _ as r -> r | Error e -> use e
end
include R.Infix
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------------------------*)

View file

@ -0,0 +1,308 @@
(*---------------------------------------------------------------------------
Copyright (c) 2014 The rresult programmers. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
---------------------------------------------------------------------------*)
(** Result value combinators.
{b Note.} OCaml 4.08 provides the {!Stdlib.Result} module
which you should prefer to [Rresult].
[Rresult] is a module for handling computation results and errors
in an explicit and declarative manner without resorting to
exceptions. It defines a {!result} type equal to OCaml 4.03's
[result] type and {{!R}combinators} to operate on these values.
Open the module to use it, this defines the {{!result}result type},
the {!R.Infix} operators {!R} in your scope.
Consult {{!usage}usage guidelines} for the type. *)
(** {1 Results} *)
(** The type for results. *)
type ('a, 'b) result = ('a, 'b) Stdlib.result = Ok of 'a | Error of 'b
val ( >>= ) : ('a, 'b) result -> ('a -> ('c, 'b) result) -> ('c, 'b) result
(** [(>>=)] is {!R.(>>=)}. *)
val ( >>| ) : ('a, 'b) result -> ('a -> 'c) -> ('c, 'b) result
(** [(>>|)] is {!R.(>>|)}. *)
(** Result value combinators. *)
module R : sig
(** {1 Results} *)
type ('a, 'b) t = ('a, 'b) result
(** The type for results. *)
val ok : 'a -> ('a, 'b) result
(** [ok v] is [Ok v]. *)
val error : 'b -> ('a, 'b) result
(** [error e] is [Error e]. *)
val reword_error : ('b -> 'c) -> ('a, 'b) result -> ('a, 'c) result
(** [reword_error reword r] is:
{ul
{- [r] if [r = Ok v]}
{- [Error (reword e)] if [r = Error e]}} *)
val get_ok : ('a, 'b) result -> 'a
(** [get_ok r] is [v] if [r = Ok v] and raises [Invalid_argument]
otherwise. *)
val get_error : ('a, 'b) result -> 'b
(** [get_error r] is [e] if [r = Error e] and raises [Invalid_argument]
otherwise. *)
(**/**)
val return : 'a -> ('a, 'b) result
val fail : 'b -> ('a, 'b) result
(**/**)
(** {1 Composing results} *)
val bind : ('a, 'b) result -> ('a -> ('c, 'b) result) -> ('c, 'b) result
(** [bind r f] is [f v] if [r = Ok v] and [r] if [r = Error _]. *)
val map : ('a -> 'c) -> ('a, 'b) result -> ('c, 'b) result
(** [map f r] is [bind (fun v -> ret (f v))] r. *)
val join : (('a, 'b) result, 'b) result -> ('a, 'b) result
(** [join r] is [v] if [r = Ok v] and [r] otherwise. *)
val ( >>= ) : ('a, 'b) result -> ('a -> ('c, 'b) result) -> ('c, 'b) result
(** [r >>= f] is {!bind}[ r f]. *)
val ( >>| ) : ('a, 'b) result -> ('a -> 'c) -> ('c, 'b) result
(** [r >>| f] is {!map}[ r f]. *)
(** Infix operators.
Gathers {!R}'s infix operators. *)
module Infix : sig
(** {1 Infix operators} *)
val ( >>= ) : ('a, 'b) result -> ('a -> ('c, 'b) result) -> ('c, 'b) result
(** [(>>=)] is {!R.(>>=)}. *)
val ( >>| ) : ('a, 'b) result -> ('a -> 'c) -> ('c, 'b) result
(** [(>>|)] is {!R.(>>|)}. *)
end
(** {1:msgs Error messages} *)
type msg = [ `Msg of string ]
(** The type for (error) messages. *)
val msg : string -> [> msg]
(** [msg s] is [`Msg s]. *)
val msgf : ('a, Format.formatter, unit, [> msg]) format4 -> 'a
(** [msgf fmt ...] formats a message according to [fmt]. *)
val pp_msg : Format.formatter -> msg -> unit
(** [pp_msg ppf m] prints [m] on [ppf]. *)
val error_msg : string -> ('a, [> msg]) result
(** [error_msg s] is [error (`Msg s)]. *)
val error_msgf : ('a, Format.formatter, unit, ('b, [> msg]) result)
format4 -> 'a
(** [error_msgf fmt ...] is an error message formatted according to [fmt]. *)
val reword_error_msg : ?replace:bool -> (string -> msg) ->
('a, msg) result -> ('a, [> msg]) result
(** [reword_error_msg ~replace reword r] is like {!reword_error} except
if [replace] is [false] (default), the result of [reword old_msg] is
concatened, on a new line to the old message. *)
val error_to_msg : pp_error:(Format.formatter -> 'b -> unit) ->
('a, 'b) result -> ('a, [> msg]) result
(** [error_to_msg ~pp_error r] converts errors in [r] with [pp_error] to
an error message. *)
val error_msg_to_invalid_arg : ('a, msg) result -> 'a
(** [err_msg_to_invalid_arg r] is [v] if [r = Ok v] and
@raise Invalid_argument with the error message otherwise. *)
val open_error_msg : ('a, msg) result -> ('a, [> msg]) result
(** [open_error_msg r] allows to combine a closed error message
variant with other variants. *)
val failwith_error_msg : ('a, msg) result -> 'a
(** [failwith_error_msg r] raises [Failure m] if [r] is
[Error (`Msg m)]. *)
(** {1:exn Trapping unexpected exceptions}
{e Getting rid of [null] was not enough}. *)
type exn_trap = [ `Exn_trap of exn * Printexc.raw_backtrace ]
(** The type for exception traps. *)
val pp_exn_trap : Format.formatter -> exn_trap -> unit
(** [pp_exn_trap ppf bt] prints [bt] on [ppf]. *)
val trap_exn : ('a -> 'b) -> 'a -> ('b, [> exn_trap]) result
(** [trap_exn f v] is [f v] and traps any exception that may occur as
an exception trap error. *)
val error_exn_trap_to_msg : ('a, exn_trap) result -> ('a, [> msg]) result
(** [error_exn_trap_to_msg r] converts exception trap errors in
[r] to an error message. *)
val open_error_exn_trap : ('a, exn_trap) result -> ('a, [> exn_trap]) result
(** [open_error_exn_trap r] allows to combine a closed exception trap error
variant with other variants. *)
(** {1:print Pretty printing} *)
val pp :
ok:(Format.formatter -> 'a -> unit) ->
error:(Format.formatter -> 'b -> unit) -> Format.formatter ->
('a, 'b) result -> unit
(** [pp ~ok ~error ppf r] prints [r] on [ppf] using [ok] and [error]
according to [r]. *)
val dump :
ok:(Format.formatter -> 'a -> unit) ->
error:(Format.formatter -> 'b -> unit) -> Format.formatter ->
('a, 'b) result -> unit
(** [dump ~ok ~error] formats an OCaml result value using [ok] or [error]
according to case, no parentheses are added. *)
(** {1:pred Predicates and comparison} *)
val is_ok : ('a, 'b) result -> bool
(** [is_ok r] is [true] iff [r = Ok _]. *)
val is_error : ('a, 'b) result -> bool
(** [is_error r] is [true] iff [r = Error _]. *)
val equal : ok:('a -> 'a -> bool) -> error:('b -> 'b -> bool) ->
('a, 'b) result -> ('a, 'b) result -> bool
(** [equal ~ok ~error r r'] tests [r] and [r'] for equality using [ok]
and [error]. *)
val compare : ok:('a -> 'a -> int) -> error:('b -> 'b -> int) ->
('a, 'b) result -> ('a, 'b) result -> int
(** [compare ~ok ~error r r'] totally orders [r] and [r'] using [ok]
and [error]. *)
(** {1:convert Converting} *)
val to_option : ('a, 'b) result -> 'a option
(** [to_option r] is [Some v] if [r = Ok v] and [None] otherwise. *)
val of_option : none:(unit -> ('a, 'b) result) -> 'a option -> ('a, 'b) result
(** [of_option ~none r] is [Ok v] if [r = Some v] and [none ()] otherwise. *)
val to_presult : ('a, 'b) result -> [> `Ok of 'a | `Error of 'b ]
(** [to_presult r] is [r] as a polymorphic variant result value. *)
val of_presult : [< `Ok of 'a | `Error of 'b ] -> ('a, 'b) result
(** [of_presult pr] is [pr] as a result value. *)
(** {1:ignore Ignoring errors}
{b Warning.} Using these functions is, most of the time, a bad idea. *)
val ignore_error : use:('b -> 'a) -> ('a, 'b) result -> 'a
(** [ignore_error ~use r] is [v] if [r = Ok v] and [use e] if
[r = Error e]. *)
val kignore_error :
use:('b -> ('a, 'c) result) -> ('a, 'b) result -> ('a, 'c) result
(** [kignore_error ~use r] is [r] if [r = Ok v] and [use e] if
[r = Error e]. *)
end
(** {1:usage Usage design guidelines}
These are rough design guidelines, don't forget to think.
{2 Error messages}
Use {{!R.msgs}error messages} if:
{ol
{- Your error messages don't need to be localized, e.g. scripts,
command line programs.}
{- The errors don't need to be processed. They are just meant to
be logged at certain point in your program.}}
If the above doesn't hold and your errors need to be processed for
localization or error recovery then use a custom error type in your
result values.
{2 Custom error types}
If your module has specific errors then define an error type, and
a result type that tags this error type with the library name (or
any other tag that may make sense, see for example {!R.exn}) along
with the following functions:
{[
module Mod : sig
type error = ...
type 'a result = ('a, [`Mod of error]) Rresult.result
val pp_error : Format.formatter -> [`Mod of error] -> unit
val open_error : 'a result -> ('a, [> `Mod of error]) Rresult.result
val error_to_msg : 'a result -> ('a, Rresult.R.msg) Rresult.result
val f : ... -> 'a result
end
]}
If your library has generic errors that may be useful in other context
or shared among modules and to be composed together, then define your
error type itself as being a variant and return these values
without tagging them.
{[
module Mod : sig
type error = [`Generic of ... | ... ]
type 'a result = ('a, error) Rresult.result
val pp_error : Format.formatter -> error -> unit
val open_error : 'a result -> ('a, [> error]) Rresult.result
val error_to_msg : 'a result -> ('a, Rresult.R.msg) Rresult.result
val f : ... -> 'a result
end
]}
In the latter case it may still be useful to provide a function to
tag these errors whenever they reach a certain point of the program.
For this the following function could be added to [Mod]:
{[
val pack_error : 'a result -> ('a, [> `Mod of error]) Rresult.result
]}
You should then provide the following functions aswell, so that
the packed error composes well in the system:
{[
val pp_pack_error : Format.formatter -> [ `Mod of error] -> unit
val open_pack_error : ('a, [ `Mod of error]) Rresult.result ->
('a, [> `Mod of error]) Rresult.result
val error_pack_to_msg : ('a, [ `Mod of error]) Rresult.result ->
('a, Rresult.R.msg) Rresult.result
]}
*)
(*---------------------------------------------------------------------------
Copyright (c) 2014 The rresult programmers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------------------------*)

View file

@ -0,0 +1 @@
Rresult

View file

@ -0,0 +1,22 @@
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
---------------------------------------------------------------------------*)
let () = ignore (Toploop.use_file Format.err_formatter "rresult_top_init.ml")
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------------------------*)

View file

@ -0,0 +1 @@
Rresult_top

View file

@ -0,0 +1,22 @@
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
---------------------------------------------------------------------------*)
open Rresult;;
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------------------------*)

View file

@ -0,0 +1,151 @@
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
---------------------------------------------------------------------------*)
open Rresult
let log f = Format.printf (f ^^ "@.")
let raises_invalid_arg f x =
try f x; raise Exit with
| Invalid_argument _ -> ()
| e -> assert false
let test_constructors () =
log "Test R.{ok,error}";
assert (R.ok 3 = Ok 3);
assert (R.error `An_error = Error `An_error);
()
let test_reword_error () =
log "Test R.reword_error";
let reword `An_error = `Another_one in
assert (R.reword_error reword (Ok 3) = Ok 3);
assert (R.reword_error reword (Error `An_error) = (Error `Another_one));
()
let test_gets () =
log "Test R.get_{ok,error}";
assert (R.get_ok (Ok 2) = 2);
assert (R.get_error (Error 3) = 3);
raises_invalid_arg R.get_ok (Error 3);
raises_invalid_arg R.get_error (Ok 2);
()
let test_bind () =
log "Test R.bind";
assert (R.bind (Ok 3) (fun v -> Error (string_of_int v)) = Error "3");
assert (R.bind (Ok 3) (fun v -> Ok (string_of_int v)) = Ok "3");
assert (R.bind (Error 1) (fun v -> Ok (string_of_int v)) = Error 1);
()
let test_map () =
log "Test R.map";
assert (R.map (fun v -> string_of_int v) (Ok 2) = Ok "2");
assert (R.map (fun v -> string_of_int v) (Error 2) = Error 2);
()
let test_join () =
log "Test R.join";
assert (R.join (Ok (Ok 3)) = Ok 3);
assert (R.join (Ok (Error 2)) = Error 2);
assert (R.join (Error 3) = Error 3);
assert (R.join (Error 4) = Error 4);
()
let test_msgs () =
log "Test error messages.";
assert (R.msg "bla" = `Msg "bla");
assert (R.msgf "bla%d" 3 = `Msg "bla3");
assert (R.error_msg "bla" = Error (`Msg "bla"));
assert (R.error_msgf "bla%d" 3 = Error (`Msg "bla3"));
let reword s = `Msg (s ^ "++") in
assert (R.reword_error_msg ~replace:true reword (Ok 2) = Ok 2);
assert (R.reword_error_msg ~replace:false reword (Ok 2) = Ok 2);
assert (R.reword_error_msg ~replace:true reword
(Error (`Msg "ha")) = (Error (`Msg "ha++")));
assert (R.reword_error_msg ~replace:false reword
(Error (`Msg "ha")) = (Error (`Msg "ha\nha++")));
let pp_error ppf = function `E -> Format.fprintf ppf "E" in
assert (R.error_to_msg ~pp_error (Ok 2) = (Ok 2));
assert (R.error_to_msg ~pp_error (Error `E) = (Error (`Msg "E")));
assert (R.error_msg_to_invalid_arg (Ok 2) = 2);
raises_invalid_arg R.error_msg_to_invalid_arg (Error (`Msg "E"));
()
let test_exn_trap () =
log "Test trapping unexpected exceptions.";
let no_raise x = string_of_int x in
let do_raise x = raise Exit in
assert (R.trap_exn no_raise 3 = Ok "3");
begin match R.trap_exn do_raise 3 with
| Ok _ -> assert false
| Error (`Exn_trap (Exit, _)) -> ()
| Error _ -> assert false
end;
()
let test_is () =
log "Test R.is_{ok,error}";
assert (R.is_ok (Ok 2));
assert (not @@ R.is_ok (Error 2));
assert (R.is_error (Error 2));
assert (not @@ R.is_error (Ok 2));
()
let test_converting () =
log "Test R.{to,of}_{option,presult}";
assert (R.to_option (Ok 3) = Some 3);
assert (R.to_option (Error 3) = None);
assert (R.of_option ~none:(fun () -> Error "none") (Some 3) = Ok 3);
assert (R.of_option ~none:(fun () -> Error "none") (None) = Error "none");
assert (R.to_presult (Ok 3) = (`Ok 3));
assert (R.to_presult (Error 3) = (`Error 3));
assert (R.of_presult (`Ok 3) = (Ok 3));
assert (R.of_presult (`Error 3) = (Error 3));
()
let test_ignoring () =
log "Test.[k]ignore_error";
assert (R.ignore_error ~use:(fun _ -> 3) (Ok 4) = 4);
assert (R.ignore_error ~use:(fun _ -> 3) (Error 4) = 3);
assert (R.kignore_error ~use:(fun _ -> Ok 3) (Ok 4) = (Ok 4));
assert (R.kignore_error ~use:(fun _ -> Ok 3) (Error 4) = (Ok 3));
assert (R.kignore_error ~use:(fun _ -> Error 3) (Ok 4) = (Ok 4));
assert (R.kignore_error ~use:(fun _ -> Error 3) (Error 4) = (Error 3));
()
let tests () =
test_constructors ();
test_reword_error ();
test_gets ();
test_bind ();
test_map ();
test_join ();
test_msgs ();
test_exn_trap ();
test_is ();
test_converting ();
test_ignoring ();
()
let () =
tests ();
log "All tests succeeded."
(*---------------------------------------------------------------------------
Copyright (c) 2015 The rresult programmers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------------------------*)