-
-
Notifications
You must be signed in to change notification settings - Fork 28
/
either.js
121 lines (109 loc) · 3.28 KB
/
either.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// @flow strict
import { annotate, indent } from 'debrief';
import { summarize } from 'debrief';
import { Err, Ok } from 'lemons/Result';
import type { Decoder } from './types';
/**
* Indents and adds a dash in front of this (potentially multiline) string.
*/
// istanbul ignore next
function itemize(s: string = ''): string {
return '-' + indent(s).substring(1);
}
export function either<T1, T2>(d1: Decoder<T1>, d2: Decoder<T2>): Decoder<T1 | T2> {
return (blob: mixed) =>
d1(blob).dispatch(
value1 => Ok(value1),
err1 =>
d2(blob).dispatch(
value2 => Ok(value2),
err2 =>
Err(
annotate(
blob,
[
'Either:',
itemize(summarize(err1).join('\n')),
itemize(summarize(err2).join('\n')),
].join('\n')
)
)
)
);
}
export function either3<T1, T2, T3>(d1: Decoder<T1>, d2: Decoder<T2>, d3: Decoder<T3>): Decoder<T1 | T2 | T3> {
return either(d1, either(d2, d3));
}
export function either4<T1, T2, T3, T4>(
d1: Decoder<T1>,
d2: Decoder<T2>,
d3: Decoder<T3>,
d4: Decoder<T4>
): Decoder<T1 | T2 | T3 | T4> {
return either(d1, either3(d2, d3, d4));
}
export function either5<T1, T2, T3, T4, T5>(
d1: Decoder<T1>,
d2: Decoder<T2>,
d3: Decoder<T3>,
d4: Decoder<T4>,
d5: Decoder<T5>
): Decoder<T1 | T2 | T3 | T4 | T5> {
return either(d1, either4(d2, d3, d4, d5));
}
export function either6<T1, T2, T3, T4, T5, T6>(
d1: Decoder<T1>,
d2: Decoder<T2>,
d3: Decoder<T3>,
d4: Decoder<T4>,
d5: Decoder<T5>,
d6: Decoder<T6>
): Decoder<T1 | T2 | T3 | T4 | T5 | T6> {
return either(d1, either5(d2, d3, d4, d5, d6));
}
export function either7<T1, T2, T3, T4, T5, T6, T7>(
d1: Decoder<T1>,
d2: Decoder<T2>,
d3: Decoder<T3>,
d4: Decoder<T4>,
d5: Decoder<T5>,
d6: Decoder<T6>,
d7: Decoder<T7>
): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7> {
return either(d1, either6(d2, d3, d4, d5, d6, d7));
}
export function either8<T1, T2, T3, T4, T5, T6, T7, T8>(
d1: Decoder<T1>,
d2: Decoder<T2>,
d3: Decoder<T3>,
d4: Decoder<T4>,
d5: Decoder<T5>,
d6: Decoder<T6>,
d7: Decoder<T7>,
d8: Decoder<T8>
): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8> {
return either(d1, either7(d2, d3, d4, d5, d6, d7, d8));
}
export function either9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
d1: Decoder<T1>,
d2: Decoder<T2>,
d3: Decoder<T3>,
d4: Decoder<T4>,
d5: Decoder<T5>,
d6: Decoder<T6>,
d7: Decoder<T7>,
d8: Decoder<T8>,
d9: Decoder<T9>
): Decoder<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9> {
return either(d1, either8(d2, d3, d4, d5, d6, d7, d8, d9));
}
export function oneOf<T>(constants: Array<T>): Decoder<T> {
return (blob: mixed) => {
for (const c of constants) {
if (c === blob) {
return Ok(c);
}
}
return Err(annotate(blob, `Must be one of ${constants.map(value => JSON.stringify(value)).join(', ')}`));
};
}