API / JavaScript / Belt / Result

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:

RE
type 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

RE
Belt.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.

RE
let 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.

RE
let 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.

RE
let 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

RE
Belt.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

RE
let 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)

RE
let 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;