Skip to content

Commit 9603edb

Browse files
committed
Use structural typeclasses for result module
1 parent 193657f commit 9603edb

7 files changed

Lines changed: 42 additions & 51 deletions

docs/decoding-variants.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ D.variantFromString(parseColor, Js.Json.string("Yellow"));
2828

2929
In other cases, `ExpectedValidOption` might not be enough debugging information. You may want custom handling (or simply more specific errors) when something goes wrong during decoding.
3030

31-
You can get this by extending the underlying `DecodeBase.failure` type with extra constructors. You use this extension to build your own custom `Decode.ParseError`, which in turn can be used to build a custom decode module on top of `DecodeBase`.
31+
You can get this by extending the underlying `Decode.ParseError.base` type with extra constructors. You use this extension to build your own custom `Decode.ParseError`, which in turn can be used to build a custom decode module on top of `DecodeBase`.
3232

3333
This may sound overwhelming, but the whole thing can be accomplished in about 6 lines of code:
3434

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
module NonEmptyList = Relude.NonEmpty.List;
22
module ParseError = Decode_ParseError;
33

4-
module ResultUtil =
4+
module Result =
55
ParseError.ResultOf({
66
type t = ParseError.base;
77
let handle = t => t;
88
});
99

10-
include DecodeBase.DecodeBase(ResultUtil.TransformError, ResultUtil.Monad);
10+
include DecodeBase.DecodeBase(Result.TransformError, Result);

src/Decode_AsResult_OfStringNel.re

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,21 @@ open Relude.Globals;
66
module NonEmptyList = NonEmpty.List;
77

88
module ResultUtil = {
9-
open BsAbstract.Interface;
109
module ParseError = Decode_ParseError;
10+
type t('a) = result('a, NonEmptyList.t(string));
1111

12-
module Monad: MONAD with type t('a) = result('a, NonEmptyList.t(string)) = {
13-
type t('a) = result('a, NonEmptyList.t(string));
14-
let map = Result.map;
15-
let apply = (a, b) =>
16-
switch (a, b) {
17-
| (Ok(f), Ok(v)) => Ok(f(v))
18-
| (Ok(_), Error(v)) => Error(v)
19-
| (Error(v), Ok(_)) => Error(v)
20-
| (Error(xa), Error(xb)) => Error(NonEmptyList.concat(xa, xb))
21-
};
22-
let pure = Result.pure;
23-
let flat_map = Result.bind;
24-
};
12+
let map = Result.map;
13+
14+
let apply = (a, b) =>
15+
switch (a, b) {
16+
| (Ok(f), Ok(v)) => Ok(f(v))
17+
| (Ok(_), Error(v)) => Error(v)
18+
| (Error(v), Ok(_)) => Error(v)
19+
| (Error(xa), Error(xb)) => Error(NonEmptyList.concat(xa, xb))
20+
};
21+
22+
let pure = Result.pure;
23+
let flat_map = Result.bind;
2524

2625
module Transform:
2726
ParseError.TransformError with
@@ -54,4 +53,4 @@ module ResultUtil = {
5453
};
5554
};
5655

57-
include DecodeBase.DecodeBase(ResultUtil.Transform, ResultUtil.Monad);
56+
include DecodeBase.DecodeBase(ResultUtil.Transform, ResultUtil);

src/Decode_ParseError.re

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -152,26 +152,22 @@ module type ValError = {
152152
};
153153

154154
module ResultOf = (Err: ValError) => {
155-
open BsAbstract.Interface;
156-
157-
type r('a) = Result.t('a, t(Err.t));
158-
159-
module Monad: MONAD with type t('a) = r('a) = {
160-
type t('a) = r('a);
161-
let map = Result.map;
162-
let apply = (f, v) =>
163-
switch (f, v) {
164-
| (Ok(fn), Ok(a)) => Result.ok(fn(a))
165-
| (Ok(_), Error(_) as err) => err
166-
| (Error(_) as err, Ok(_)) => err
167-
| (Error(fnx), Error(ax)) => Result.error(combine(fnx, ax))
168-
};
169-
let pure = Result.pure;
170-
let flat_map = Result.bind;
171-
};
155+
type error = t(Err.t);
156+
type nonrec t('a) = result('a, error);
157+
let map = Result.map;
158+
let apply = (f, v) =>
159+
switch (f, v) {
160+
| (Ok(fn), Ok(a)) => Result.ok(fn(a))
161+
| (Ok(_), Error(_) as err) => err
162+
| (Error(_) as err, Ok(_)) => err
163+
| (Error(fnx), Error(ax)) => Result.error(combine(fnx, ax))
164+
};
165+
166+
let pure = Result.pure;
167+
let flat_map = Result.bind;
172168

173-
module TransformError: TransformError with type t('a) = r('a) = {
174-
type t('a) = r('a);
169+
module TransformError: TransformError with type t('a) = result('a, error) = {
170+
type t('a) = result('a, error);
175171

176172
let valErr = (v, json) => Result.error(Val(Err.handle(v), json));
177173
let arrErr = pos => Result.mapError(arrPure(pos));

src/Decode_ParseError.rei

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,15 @@ module type ValError = {
4949
module ResultOf:
5050
(Err: ValError) =>
5151
{
52-
module Monad: {
53-
type nonrec t('a) = result('a, t(Err.t));
54-
let map: ('a => 'b, t('a)) => t('b);
55-
let apply: (t('a => 'b), t('a)) => t('b);
56-
let pure: 'a => t('a);
57-
let flat_map: (t('a), 'a => t('b)) => t('b);
58-
};
52+
type error = t(Err.t);
53+
type nonrec t('a) = result('a, error);
54+
let map: ('a => 'b, t('a)) => t('b);
55+
let apply: (t('a => 'b), t('a)) => t('b);
56+
let pure: 'a => t('a);
57+
let flat_map: (t('a), 'a => t('b)) => t('b);
5958

6059
module TransformError: {
61-
type nonrec t('a) = result('a, t(Err.t));
60+
type nonrec t('a) = result('a, error);
6261
let valErr: (base, Js.Json.t) => t('a);
6362
let arrErr: (int, t('a)) => t('a);
6463
let missingFieldErr: string => t('a);

test/Decode_AsOption_test.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ describe("Decode records", () => {
531531
[@bs.module] external bigjson: Js.Json.t = "./utils/BigJson.json";
532532

533533
describe("Big JSON array", () =>
534-
test("Doesn't blow up", () =>
534+
test("is stack-safe", () =>
535535
expect(Decode.array(Option.pure, bigjson) |> Option.isSome)
536536
|> toEqual(true)
537537
)

test/Decode_AsResult_OfCustom_test.re

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,14 @@ module Sample = Decode_TestSampleData;
1111

1212
type customError = [ ParseError.base | `InvalidColor | `InvalidShape];
1313

14-
module ResultOfCustomError =
14+
module ResultCustom =
1515
Decode.ParseError.ResultOf({
1616
type t = customError;
1717
let handle = x => (x :> t);
1818
});
1919

2020
module Decode =
21-
DecodeBase.DecodeBase(
22-
ResultOfCustomError.TransformError,
23-
ResultOfCustomError.Monad,
24-
);
21+
DecodeBase.DecodeBase(ResultCustom.TransformError, ResultCustom);
2522

2623
let toDebugString = (err, json) =>
2724
switch (err) {

0 commit comments

Comments
 (0)