Skip to content

Commit 2e6fc0c

Browse files
committed
Result.mapError
1 parent 3b84757 commit 2e6fc0c

File tree

5 files changed

+87
-0
lines changed

5 files changed

+87
-0
lines changed

src/Core__Result.mjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ function forEach(r, f) {
109109

110110
}
111111

112+
function mapError(r, f) {
113+
if (r.TAG === /* Ok */0) {
114+
return r;
115+
} else {
116+
return {
117+
TAG: /* Error */1,
118+
_0: Curry._1(f, r._0)
119+
};
120+
}
121+
}
122+
112123
export {
113124
getExn ,
114125
mapWithDefault ,
@@ -120,5 +131,6 @@ export {
120131
eq ,
121132
cmp ,
122133
forEach ,
134+
mapError ,
123135
}
124136
/* No side effect */

src/Core__Result.res

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,15 @@ let forEach = (r, f) =>
9797
| Ok(ok) => f(ok)
9898
| Error(_) => ()
9999
}
100+
101+
// If the source result is Ok, should we return that instance, or
102+
// create it again? In this implementation I'm returning that specific
103+
// instance. However this is not consistent with the implementation for
104+
// other functions like mapU and flatMapU, which recreate the result.
105+
// This is more efficient. I'm not sure why the other implementations
106+
// return a new instance.
107+
let mapError = (r, f) =>
108+
switch r {
109+
| Ok(_) as ok => ok
110+
| Error(e) => Error(f(e))
111+
}

src/Core__Result.resi

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,17 @@ Result.forEach(Error("x"), Console.log) // Does nothing, returns ()
209209
```
210210
*/
211211
let forEach: (t<'a, 'b>, 'a => unit) => unit
212+
213+
/**
214+
`mapError(res, f)` - If the source is `Ok`, return it. Otherwise apply
215+
the function `f` to the `Error` value.
216+
217+
## Examples
218+
```rescript
219+
220+
let formatError = n => `Error code: ${n->Int.toString}`
221+
mapError(Error(14), formatError) // evaluates to Error("Error code: 14")
222+
mapError(Ok("abc"), formatError) // evaluates to Ok("abc")
223+
```
224+
*/
225+
let mapError: (result<'a, 'b>, 'b => 'c) => result<'a, 'c>

test/ResultTests.mjs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,42 @@ function forEachIfErrorDoNotCallFunction(param) {
5252

5353
forEachIfErrorDoNotCallFunction(undefined);
5454

55+
Test.run([
56+
[
57+
"ResultTests.res",
58+
27,
59+
20,
60+
48
61+
],
62+
"mapError: if ok, return it"
63+
], Core__Result.mapError({
64+
TAG: /* Ok */0,
65+
_0: 5
66+
}, (function (i) {
67+
return Math.imul(i, 3);
68+
})), eq, {
69+
TAG: /* Ok */0,
70+
_0: 5
71+
});
72+
73+
Test.run([
74+
[
75+
"ResultTests.res",
76+
30,
77+
13,
78+
42
79+
],
80+
"mapError: if error, apply f"
81+
], Core__Result.mapError({
82+
TAG: /* Error */1,
83+
_0: 5
84+
}, (function (i) {
85+
return Math.imul(i, 3);
86+
})), eq, {
87+
TAG: /* Error */1,
88+
_0: 15
89+
});
90+
5591
export {
5692
eq ,
5793
forEachIfOkCallFunction ,

test/ResultTests.res

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,16 @@ let forEachIfErrorDoNotCallFunction = () => {
1919
Test.run(__POS_OF__("forEach: if error, do not call function"), called.contents, eq, [])
2020
}
2121
forEachIfErrorDoNotCallFunction()
22+
23+
// ========
24+
// mapError
25+
// ========
26+
27+
Test.run(__POS_OF__("mapError: if ok, return it"), Ok(5)->Result.mapError(i => i * 3), eq, Ok(5))
28+
29+
Test.run(
30+
__POS_OF__("mapError: if error, apply f"),
31+
Error(5)->Result.mapError(i => i * 3),
32+
eq,
33+
Error(15),
34+
)

0 commit comments

Comments
 (0)