Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#### :rocket: New Feature

- Add `littleEndian` feature for `DataView` to Stdlib. https://github.com/rescript-lang/rescript/pull/7881
- Add `mapOkAsync`, `mapErrorAsync`, `flatMapOkAsync` and `flatMapErrorAsync` for async `result`'s to Stdlib. https://github.com/rescript-lang/rescript/pull/7906

#### :bug: Bug fix

Expand Down
24 changes: 24 additions & 0 deletions packages/@rescript/runtime/Stdlib_Result.res
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,27 @@ let all6 = ((a, b, c, d, e, f)) => {
}

external ignore: result<'res, 'err> => unit = "%ignore"

let mapOkAsync = async (res, f) =>
switch await res {
| Ok(value) => Ok(f(value))
| Error(err) => Error(err)
}

let mapErrorAsync = async (res, f) =>
switch await res {
| Ok(value) => Ok(value)
| Error(err) => Error(f(err))
}

let flatMapOkAsync = async (res, f) =>
switch await res {
| Ok(value) => await f(value)
| Error(err) => Error(err)
}

let flatMapErrorAsync = async (res, f) =>
switch await res {
| Ok(value) => Ok(value)
| Error(err) => await f(err)
}
118 changes: 102 additions & 16 deletions packages/@rescript/runtime/Stdlib_Result.resi
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ type t<'res, 'err> = result<'res, 'err> = Ok('res) | Error('err)
Result.getExn(Result.Ok(42)) == 42

switch Result.getExn(Error("Invalid data")) {
| exception _ => assert(true)
| _ => assert(false)
}
| exception _ => true
| _ => false
} == true

switch Result.getExn(Error("Invalid data"), ~message="was Error!") {
| exception _ => assert(true) // Throws a JsError with the message "was Error!"
| _ => assert(false)
}
| exception _ => true // Throws a JsError with the message "was Error!"
| _ => false
} == true
```
*/
@deprecated("Use 'getOrThrow' instead")
Expand All @@ -74,14 +74,14 @@ let getExn: (result<'a, 'b>, ~message: string=?) => 'a
Result.getOrThrow(Result.Ok(42)) == 42

switch Result.getOrThrow(Error("Invalid data")) {
| exception _ => assert(true)
| _ => assert(false)
}
| exception _ => true
| _ => false
} == true

switch Result.getOrThrow(Error("Invalid data"), ~message="was Error!") {
| exception _ => assert(true) // Throws a JsError with the message "was Error!"
| _ => assert(false)
}
| exception _ => true // Throws a JsError with the message "was Error!"
| _ => false
} == true
```
*/
let getOrThrow: (result<'a, 'b>, ~message: string=?) => 'a
Expand Down Expand Up @@ -259,8 +259,8 @@ let forEach: (result<'a, 'b>, 'a => unit) => unit

```rescript
let format = n => `Error code: ${n->Int.toString}`
Result.mapError(Error(14), format) // Error("Error code: 14")
Result.mapError(Ok("abc"), format) // Ok("abc")
Result.mapError(Error(14), format) == Error("Error code: 14")
Result.mapError(Ok("abc"), format) == Ok("abc")
```
*/
let mapError: (result<'a, 'b>, 'b => 'c) => result<'a, 'c>
Expand All @@ -269,8 +269,8 @@ let mapError: (result<'a, 'b>, 'b => 'c) => result<'a, 'c>
`all(results)` returns a result of array if all options are Ok, otherwise returns Error.
## Examples
```rescript
Result.all([Ok(1), Ok(2), Ok(3)]) // Ok([1, 2, 3])
Result.all([Ok(1), Error(1)]) // Error(1)
Result.all([Ok(1), Ok(2), Ok(3)]) == Ok([1, 2, 3])
Result.all([Ok(1), Error(1)]) == Error(1)
```
*/
let all: array<result<'a, 'b>> => result<array<'a>, 'b>
Expand Down Expand Up @@ -321,3 +321,89 @@ let all6: (
without having to store or process it further.
*/
external ignore: result<'res, 'err> => unit = "%ignore"

/**
`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 asyncSquare = async x => x * x

let result1 = Result.mapOkAsync(Promise.resolve(Ok(4)), asyncSquare) // Returns promise that resolves to Ok(16)
let result2 = Result.mapOkAsync(Promise.resolve(Error("invalid")), asyncSquare) // Returns promise that resolves to Error("invalid")
```
*/
let mapOkAsync: (
promise<result<'ok, 'error>>,
'ok => 'mappedOk,
) => promise<result<'mappedOk, 'error>>

/**
`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

```rescript
let asyncFormatError = async e => `Error: ${e}`

let result1 = Result.mapErrorAsync(Promise.resolve(Ok(42)), asyncFormatError) // Returns promise that resolves to Ok(42)
let result2 = Result.mapErrorAsync(Promise.resolve(Error("invalid")), asyncFormatError) // Returns promise that resolves to Error("Error: invalid")
```
*/
let mapErrorAsync: (
promise<result<'ok, 'error>>,
'error => 'mappedError,
) => promise<result<'ok, 'mappedError>>

/**
`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

```rescript
let asyncValidate = async x =>
if x > 0 {
Ok(x * 2)
} else {
Error("Must be positive")
}

let result1 = Result.flatMapOkAsync(Promise.resolve(Ok(5)), asyncValidate) // Returns promise that resolves to Ok(10)
let result2 = Result.flatMapOkAsync(Promise.resolve(Error("Already failed")), asyncValidate) // Returns promise that resolves to Error("Already failed")
```
*/
let flatMapOkAsync: (
promise<result<'ok, 'error>>,
'ok => promise<result<'mappedOk, 'error>>,
) => promise<result<'mappedOk, 'error>>

/**
`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

```rescript
let asyncRecover = async error =>
if error === "timeout" {
Ok("default")
} else {
Error(error)
}

let result1 = Result.flatMapErrorAsync(Promise.resolve(Error("timeout")), asyncRecover) // Returns promise that resolves to Ok("default")
let result2 = Result.flatMapErrorAsync(Promise.resolve(Ok("default")), asyncRecover) // Returns promise that resolves to Ok("default")
```
*/
let flatMapErrorAsync: (
promise<result<'ok, 'error>>,
'error => promise<result<'ok, 'mappedError>>,
) => promise<result<'ok, 'mappedError>>
58 changes: 58 additions & 0 deletions packages/@rescript/runtime/lib/es6/Stdlib_Result.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,60 @@ function all6(param) {
}
}

async function mapOkAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return {
TAG: "Ok",
_0: f(value._0)
};
} else {
return {
TAG: "Error",
_0: value._0
};
}
}

async function mapErrorAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return {
TAG: "Ok",
_0: value._0
};
} else {
return {
TAG: "Error",
_0: f(value._0)
};
}
}

async function flatMapOkAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return await f(value._0);
} else {
return {
TAG: "Error",
_0: value._0
};
}
}

async function flatMapErrorAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return {
TAG: "Ok",
_0: value._0
};
} else {
return await f(value._0);
}
}

let getExn = getOrThrow;

let mapWithDefault = mapOr;
Expand Down Expand Up @@ -368,5 +422,9 @@ export {
all4,
all5,
all6,
mapOkAsync,
mapErrorAsync,
flatMapOkAsync,
flatMapErrorAsync,
}
/* No side effect */
58 changes: 58 additions & 0 deletions packages/@rescript/runtime/lib/js/Stdlib_Result.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,60 @@ function all6(param) {
}
}

async function mapOkAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return {
TAG: "Ok",
_0: f(value._0)
};
} else {
return {
TAG: "Error",
_0: value._0
};
}
}

async function mapErrorAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return {
TAG: "Ok",
_0: value._0
};
} else {
return {
TAG: "Error",
_0: f(value._0)
};
}
}

async function flatMapOkAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return await f(value._0);
} else {
return {
TAG: "Error",
_0: value._0
};
}
}

async function flatMapErrorAsync(res, f) {
let value = await res;
if (value.TAG === "Ok") {
return {
TAG: "Ok",
_0: value._0
};
} else {
return await f(value._0);
}
}

let getExn = getOrThrow;

let mapWithDefault = mapOr;
Expand All @@ -367,4 +421,8 @@ exports.all3 = all3;
exports.all4 = all4;
exports.all5 = all5;
exports.all6 = all6;
exports.mapOkAsync = mapOkAsync;
exports.mapErrorAsync = mapErrorAsync;
exports.flatMapOkAsync = flatMapOkAsync;
exports.flatMapErrorAsync = flatMapErrorAsync;
/* No side effect */
Loading