Result
Result types are really useful to describe the result of a certain operation
without relying on exceptions or option
types.
This module gives you useful utilities to create and combine Result
data.
type t('a, 'b) =
| Ok('a)
| Error('b);
The type Result.t(result, err)
describes a variant of two states:
Ok(someResult)
represents a successful operation, whereby
`Error(someError)
signals an erronous operation.
In this concrete example, we are defining our own Result
type to reflect an HTTP like
query operation:
REtype responseError = NotAvailable | NotFound;
type queryResult = Belt.Result.t(string, responseError);
let failQueryUser = (username: string): queryResult => {
Error(NotAvailable)
};
let getExn: t('a, 'b) => 'a;
getExn(res)
: when res
is Ok(n)
, returns n
when res
is Error(m)
, raise an exception
REBelt.Result.getExn(Belt.Result.Ok(42)) == 42;
Belt.Result.getExn(Belt.Result.Error("Invalid data")); /* raises exception */
let mapWithDefaultU: (t('a, 'c), 'b, (.'a => 'b)) => 'b;
let mapWithDefault: (t('a, 'c), 'b, 'a => 'b) => 'b;
mapWithDefault(res, default, f);
: When res is Ok(n)
, returns f(n)
,
otherwise default
.
RElet ok = Belt.Result.Ok(42)
Belt.Result.mapWithDefault(ok, 0, (x) => x / 2) == 21;
let error = Belt.Result.Error("Invalid data")
Belt.Result.mapWithDefault(error, 0, (x) => x / 2) == 0;
let mapU: (t('a, 'c), [@bs] ('a => 'b)) => t('b, 'c);
let map: (t('a, 'c), 'a => 'b) => t('b, 'c);
map(res, f)
: When res is Ok(n)
, returns Ok(f(n))
. Otherwise returns res
unchanged. Function f
takes a value of the same type as n
and returns an
ordinary value.
RElet f = (x) => sqrt(float_of_int(x));
Belt.Result.map(Ok(64), f) == Ok(8.0);
Belt.Result.map(Error("Invalid data"), f) == Error("Invalid data");
let flatMapU: (t('a, 'c), [@bs] ('a => t('b, 'c))) => t('b, 'c);
let flatMap: (t('a, 'c), 'a => t('b, 'c)) => t('b, 'c);
flatMap(res, f)
: When res is Ok(n)
, returns f(n)
. Otherwise, returns res
unchanged. Function f
takes a value of the same type as n
and returns a
Belt.Result
.
RElet recip = (x) =>
if (x !== 0.0) {
Belt.Result.Ok(1.0 /. x);
} else {
Belt.Result.Error("Divide by zero");
};
Belt.Result.flatMap(Ok(2.0), recip) == Ok(0.5);
Belt.Result.flatMap(Ok(0.0), recip) == Error("Divide by zero");
Belt.Result.flatMap(Error("Already bad"), recip) == Error("Already bad");
let getWithDefault: (t('a, 'b), 'a) => 'a;
getWithDefault(res, defaultValue)
: If res
is Ok(n)
, returns n
,
otherwise default
REBelt.Result.getWithDefault(Ok(42), 0) == 42;
Belt.Result.getWithDefault(Error("Invalid Data"), 0) == 0;
let isOk: t('a, 'b) => bool;
isOk(res)
: Returns true
if res
is of the form Ok(n)
, false
if it is
the Error(e)
variant.
let isError: t('a, 'b) => bool;
isError(res)
: Returns true
if res
is of the form Error(e)
, false
if
it is the Ok(n)
variant.
let eqU: (t('a, 'c), t('b, 'd), (.'a, 'b) => bool) => bool;
let eq: (t('a, 'c), t('b, 'd), ('a, 'b) => bool) => bool;
eq(res1, res2, f)
: Determine if two Belt.Result
variables are equal with
respect to an equality function. If res1
and res2
are of the form Ok(n)
and Ok(m)
, return the result of f(n, m)
. If one of res1
and res2
are of
the form Error(e)
, return false If both res1
and res2
are of the form
Error(e)
, return true
RElet good1 = Belt.Result.Ok(42);
let good2 = Belt.Result.Ok(32);
let bad1 = Belt.Result.Error("invalid");
let bad2 = Belt.Result.Error("really invalid");
let mod10equal = (a, b) => a mod 10 === b mod 10;
Belt.Result.eq(good1, good2, mod10equal) == true;
Belt.Result.eq(good1, bad1, mod10equal) == false;
Belt.Result.eq(bad2, good2, mod10equal) == false;
Belt.Result.eq(bad1, bad2, mod10equal) == true;
let cmpU: (t('a, 'c), t('b, 'd), (.'a, 'b) => int) => int;
let cmp: (t('a, 'c), t('b, 'd), ('a, 'b) => int) => int;
cmp(res1, res2, f)
: Compare two Belt.Result
variables with respect to a
comparison function. The comparison function returns -1 if the first variable
is "less than" the second, 0 if the two variables are equal, and 1 if the first
is "greater than" the second.
If res1
and res2
are of the form Ok(n)
and Ok(m)
, return the result of
f(n, m)
. If res1
is of the form Error(e)
and res2
of the form Ok(n)
,
return -1 (nothing is less than something) If res1
is of the form Ok(n)
and
res2
of the form Error(e)
, return 1 (something is greater than nothing) If
both res1
and res2
are of the form Error(e)
, return 0 (equal)
RElet good1 = Belt.Result.Ok(59);
let good2 = Belt.Result.Ok(37);
let bad1 = Belt.Result.Error("invalid");
let bad2 = Belt.Result.Error("really invalid");
let mod10cmp = (a, b) => Pervasives.compare(a mod 10, b mod 10);
Belt.Result.cmp(Ok(39), Ok(57), mod10cmp) == 1;
Belt.Result.cmp(Ok(57), Ok(39), mod10cmp) == (-1);
Belt.Result.cmp(Ok(39), Error("y"), mod10cmp) == 1;
Belt.Result.cmp(Error("x"), Ok(57), mod10cmp) == (-1);
Belt.Result.cmp(Error("x"), Error("y"), mod10cmp) == 0;