Result
t
type t<'res, 'err> = result<'res, 'err> =
| Ok('res)
| Error('err)
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.
getExn
Deprecated
let getExn: (result<'a, 'b>, ~message: string=?) => 'a
getExn(res, ~message=?)
returns n
if res
is Ok(n)
, otherwise throws an exception with the message provided, or a generic message if no message was provided.
RESResult.getExn(Result.Ok(42)) == 42
switch Result.getExn(Error("Invalid data")) {
| exception _ => true
| _ => false
} == true
switch Result.getExn(Error("Invalid data"), ~message="was Error!") {
| exception _ => true // Throws a JsError with the message "was Error!"
| _ => false
} == true
getOrThrow
let getOrThrow: (result<'a, 'b>, ~message: string=?) => 'a
getOrThrow(res, ~message=?)
returns n
if res
is Ok(n)
, otherwise throws an exception with the message provided, or a generic message if no message was provided.
RESResult.getOrThrow(Result.Ok(42)) == 42
switch Result.getOrThrow(Error("Invalid data")) {
| exception _ => true
| _ => false
} == true
switch Result.getOrThrow(Error("Invalid data"), ~message="was Error!") {
| exception _ => true // Throws a JsError with the message "was Error!"
| _ => false
} == true
mapOr
let mapOr: (result<'a, 'c>, 'b, 'a => 'b) => 'b
mapOr(res, default, f)
: When res is Ok(n)
, returns f(n)
, otherwise default
.
Examples
RESCRIPTlet ok = Ok(42)
Result.mapOr(ok, 0, x => x / 2) == 21
let error = Error("Invalid data")
Result.mapOr(error, 0, x => x / 2) == 0
mapWithDefault
Deprecated
let mapWithDefault: (result<'a, 'c>, 'b, 'a => 'b) => 'b
map
let map: (result<'a, 'c>, 'a => 'b) => result<'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.
Examples
RESCRIPTlet f = x => sqrt(Int.toFloat(x))
Result.map(Ok(64), f) == Ok(8.0)
Result.map(Error("Invalid data"), f) == Error("Invalid data")
flatMap
let flatMap: (result<'a, 'c>, 'a => result<'b, 'c>) => result<'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
Result
.
Examples
RESCRIPTlet recip = x =>
if x !== 0.0 {
Ok(1.0 /. x)
} else {
Error("Divide by zero")
}
Result.flatMap(Ok(2.0), recip) == Ok(0.5)
Result.flatMap(Ok(0.0), recip) == Error("Divide by zero")
Result.flatMap(Error("Already bad"), recip) == Error("Already bad")
getOr
let getOr: (result<'a, 'b>, 'a) => 'a
getOr(res, defaultValue)
: If res
is Ok(n)
, returns n
, otherwise default
Examples
RESCRIPTResult.getOr(Ok(42), 0) == 42
Result.getOr(Error("Invalid Data"), 0) == 0
getWithDefault
Deprecated
let getWithDefault: (result<'a, 'b>, 'a) => 'a
isOk
let isOk: result<'a, 'b> => bool
isOk(res)
: Returns true
if res
is of the form Ok(n)
, false
if it is the Error(e)
variant.
isError
let isError: result<'a, 'b> => bool
isError(res)
: Returns true
if res
is of the form Error(e)
, false
if it is the Ok(n)
variant.
equal
let equal: (
result<'a, 'c>,
result<'b, 'd>,
('a, 'b) => bool,
('c, 'd) => bool,
) => bool
equal(res1, res2, eqOk, eqError)
: Determine if two Result
variables are equal with
respect to equality functions. If res1
and res2
are of the form Ok(n)
and Ok(m)
, return the result of eqOk(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 the result of eqError(e1, e2)
.
Examples
RESCRIPTlet good1 = Ok(42)
let good2 = Ok(32)
let bad1 = Error("invalid")
let bad2 = Error("really invalid")
let mod10equal = (a, b) => mod(a, 10) === mod(b, 10)
Result.equal(good1, good2, mod10equal, String.equal) == true
Result.equal(good1, bad1, mod10equal, String.equal) == false
Result.equal(bad2, good2, mod10equal, String.equal) == false
Result.equal(bad1, bad2, mod10equal, String.equal) == false
compare
let compare: (
result<'a, 'c>,
result<'b, 'd>,
('a, 'b) => Ordering.t,
('c, 'd) => Ordering.t,
) => Ordering.t
compare(res1, res2, cmpOk, cmpError)
: Compare two 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
cmpOk(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
is of the form Error(e)
, return 1. (something is greater than nothing) If
both res1
and res2
are of the form Error(e)
, return cmpError(e1, e2).
Examples
RESCRIPTlet good1 = Ok(59)
let good2 = Ok(37)
let bad1 = Error("invalid")
let bad2 = Error("really invalid")
let mod10cmp = (a, b) => Int.compare(mod(a, 10), mod(b, 10))
Result.compare(Ok(39), Ok(57), mod10cmp, String.compare) == 1.
Result.compare(Ok(57), Ok(39), mod10cmp, String.compare) == -1.
Result.compare(Ok(39), Error("y"), mod10cmp, String.compare) == 1.
Result.compare(Error("x"), Ok(57), mod10cmp, String.compare) == -1.
Result.compare(Error("x"), Error("y"), mod10cmp, String.compare) == -1.
forEach
let forEach: (result<'a, 'b>, 'a => unit) => unit
forEach(res, f)
runs the provided function f
on the Ok
value. If res
is Error
, nothing happens.
Examples
RESCRIPTResult.forEach(Ok(3), Console.log) // Logs "3", returns ()
Result.forEach(Error("x"), Console.log) // Does nothing, returns ()
mapError
let mapError: (result<'a, 'b>, 'b => 'c) => result<'a, 'c>
mapError(r, f)
generates a new result
by applying the function f
to the Error
value. If the source is Ok
, return it as-is.
Examples
RESCRIPTlet format = n => `Error code: ${n->Int.toString}`
Result.mapError(Error(14), format) == Error("Error code: 14")
Result.mapError(Ok("abc"), format) == Ok("abc")
all
let all: array<result<'a, 'b>> => result<array<'a>, 'b>
all(results)
returns a result of array if all options are Ok, otherwise returns Error.
Examples
RESCRIPTResult.all([Ok(1), Ok(2), Ok(3)]) == Ok([1, 2, 3])
Result.all([Ok(1), Error(1)]) == Error(1)
all2
let all2: (
(result<'r1, 'e>, result<'r2, 'e>),
) => result<('r1, 'r2), 'e>
all2((r1, r2))
. Like all()
, but with a fixed size tuple of 2
all3
let all3: (
(result<'r1, 'e>, result<'r2, 'e>, result<'r3, 'e>),
) => result<('r1, 'r2, 'r3), 'e>
all3((r1, r2, r3))
. Like all()
, but with a fixed size tuple of 2
all4
let all4: (
(
result<'r1, 'e>,
result<'r2, 'e>,
result<'r3, 'e>,
result<'r4, 'e>,
),
) => result<('r1, 'r2, 'r3, 'r4), 'e>
all4((r1, r2, r3, r4))
. Like all()
, but with a fixed size tuple of 2
all5
let all5: (
(
result<'r1, 'e>,
result<'r2, 'e>,
result<'r3, 'e>,
result<'r4, 'e>,
result<'r5, 'e>,
),
) => result<('r1, 'r2, 'r3, 'r4, 'r5), 'e>
all5((r1, r2, r3, r4, r5))
. Like all()
, but with a fixed size tuple of 2
all6
let all6: (
(
result<'r1, 'e>,
result<'r2, 'e>,
result<'r3, 'e>,
result<'r4, 'e>,
result<'r5, 'e>,
result<'r6, 'e>,
),
) => result<('r1, 'r2, 'r3, 'r4, 'r5, 'r6), 'e>
all6((r1, r2, r3, r4, r5, r6))
. Like all()
, but with a fixed size tuple of 2
ignore
let ignore: result<'res, 'err> => unit
ignore(result)
ignores the provided result and returns unit.
This helper is useful when you want to discard a value (for example, the result of an operation with side effects) without having to store or process it further.
mapOkAsync
let mapOkAsync: (
promise<result<'ok, 'error>>,
'ok => 'mappedOk,
) => promise<result<'mappedOk, 'error>>
mapOkAsync(res, f)
: Asynchronously maps over the Ok value of a Result. When res
is Ok(n)
,
applies the async function f
to n
and wraps the result in Ok
.
When res
is Error
, returns the error unchanged.
Examples
RESCRIPT let square = x => x * x
let result1 = await Result.mapOkAsync(Promise.resolve(Ok(4)), square)
result1 == Ok(16)
let result2 = await Result.mapOkAsync(
Promise.resolve(Error("invalid")),
square,
)
result2 == Error("invalid")
mapErrorAsync
let mapErrorAsync: (
promise<result<'ok, 'error>>,
'error => 'mappedError,
) => promise<result<'ok, 'mappedError>>
mapErrorAsync(res, f)
: Asynchronously maps over the Error value of a Result. When res
is Error(e)
,
applies the async function f
to e
and wraps the result in Error
.
When res
is Ok
, returns the ok value unchanged.
Examples
RESCRIPTlet formatError = e => `Error: ${e}`
let result1 = await Result.mapErrorAsync(Promise.resolve(Ok(42)), formatError)
result1 == Ok(42)
let result2 = await Result.mapErrorAsync(Promise.resolve(Error("invalid")), formatError)
result2 == Error("Error: invalid")
flatMapOkAsync
let flatMapOkAsync: (
promise<result<'ok, 'error>>,
'ok => promise<result<'mappedOk, 'error>>,
) => promise<result<'mappedOk, 'error>>
flatMapOkAsync(res, f)
: Asynchronously flat-maps over the Ok value of a Result. When res
is Ok(n)
,
applies the async function f
to n
which returns a Promise of a Result.
When res
is Error
, returns the error unchanged.
Examples
RESCRIPTlet asyncValidate = async x =>
if x > 0 {
Ok(x * 2)
} else {
Error("Must be positive")
}
let result1 = await Result.flatMapOkAsync(Promise.resolve(Ok(5)), asyncValidate)
result1 == Ok(10)
let result2 = await Result.flatMapOkAsync(
Promise.resolve(Error("Already failed")),
asyncValidate,
)
result2 == Error("Already failed")
flatMapErrorAsync
let flatMapErrorAsync: (
promise<result<'ok, 'error>>,
'error => promise<result<'ok, 'mappedError>>,
) => promise<result<'ok, 'mappedError>>
flatMapErrorAsync(res, f)
: Asynchronously flat-maps over the Error value of a Result. When res
is Error(e)
,
applies the async function f
to e
which returns a Promise of a Result.
When res
is Ok
, returns the ok value unchanged.
Examples
RESCRIPTlet asyncRecover = async error =>
if error === "timeout" {
Ok("default")
} else {
Error(error)
}
let result1 = await Result.flatMapErrorAsync(
Promise.resolve(Error("timeout")),
asyncRecover,
)
result1 == Ok("default")
let result2 = await Result.flatMapErrorAsync(
Promise.resolve(Ok("default")),
asyncRecover,
)
result2 == Ok("default")