aang 2.0.0-alpha.3 → 2.0.0-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/task.js ADDED
@@ -0,0 +1,282 @@
1
+ import { None, Some } from "./option.js";
2
+ import { Pair } from "./pair.js";
3
+ import { Fail, Okay } from "./result.js";
4
+ export class Task {
5
+ execute;
6
+ constructor(execute) {
7
+ this.execute = execute;
8
+ }
9
+ static okay(value) {
10
+ return new Task((signal, callback) => {
11
+ if (!signal.aborted)
12
+ callback(new Okay(value));
13
+ });
14
+ }
15
+ static fail(value) {
16
+ return new Task((signal, callback) => {
17
+ if (!signal.aborted)
18
+ callback(new Fail(value));
19
+ });
20
+ }
21
+ static of(task) {
22
+ return new Task((signal, callback) => {
23
+ const abort = task((result) => {
24
+ if (!signal.aborted) {
25
+ signal.removeEventListener("abort", onAbort);
26
+ callback(result);
27
+ }
28
+ });
29
+ signal.addEventListener("abort", onAbort);
30
+ function onAbort() {
31
+ signal.removeEventListener("abort", onAbort);
32
+ abort(signal.reason);
33
+ }
34
+ });
35
+ }
36
+ // TODO: <A, B>(getGenerator: () => Generator<Task<A, unknown>, B, A>) => Task<B, unknown>
37
+ static fromGenerator(getGenerator) {
38
+ return new Task((signal, callback) => {
39
+ const generator = getGenerator();
40
+ const trampoline = (task) => {
41
+ let option = new Some(task);
42
+ while (option.isSome) {
43
+ const task = option.value;
44
+ option = None.instance;
45
+ let isAsync = false;
46
+ task.execute(signal, (result) => {
47
+ let iteratorResult;
48
+ try {
49
+ iteratorResult = result.isOkay
50
+ ? generator.next(result.value)
51
+ : generator.throw(result.value);
52
+ }
53
+ catch (error) {
54
+ return callback(new Fail(error));
55
+ }
56
+ if (iteratorResult.done)
57
+ callback(new Okay(iteratorResult.value));
58
+ else if (isAsync)
59
+ trampoline(iteratorResult.value);
60
+ else
61
+ option = new Some(iteratorResult.value);
62
+ });
63
+ isAsync = true;
64
+ }
65
+ };
66
+ let iteratorResult;
67
+ try {
68
+ iteratorResult = generator.next();
69
+ }
70
+ catch (error) {
71
+ return callback(new Fail(error));
72
+ }
73
+ if (iteratorResult.done)
74
+ callback(new Okay(iteratorResult.value));
75
+ else
76
+ trampoline(iteratorResult.value);
77
+ });
78
+ }
79
+ run(callback) {
80
+ const controller = new AbortController();
81
+ this.execute(controller.signal, callback);
82
+ return controller;
83
+ }
84
+ map(okayMorphism, failMorphism) {
85
+ return new Task((signal, callback) => this.execute(signal, (result) => callback(result.map(okayMorphism, failMorphism))));
86
+ }
87
+ mapOkay(morphism) {
88
+ return new Task((signal, callback) => this.execute(signal, (result) => callback(result.mapOkay(morphism))));
89
+ }
90
+ mapFail(morphism) {
91
+ return new Task((signal, callback) => this.execute(signal, (result) => callback(result.mapFail(morphism))));
92
+ }
93
+ replace(okayValue, failValue) {
94
+ return new Task((signal, callback) => this.execute(signal, (result) => callback(result.replace(okayValue, failValue))));
95
+ }
96
+ replaceOkay(value) {
97
+ return new Task((signal, callback) => this.execute(signal, (result) => callback(result.replaceOkay(value))));
98
+ }
99
+ replaceFail(value) {
100
+ return new Task((signal, callback) => this.execute(signal, (result) => callback(result.replaceFail(value))));
101
+ }
102
+ and(that) {
103
+ return Task.of((callback) => {
104
+ const controller = new AbortController();
105
+ let fst = None.instance;
106
+ let snd = None.instance;
107
+ this.execute(controller.signal, (result) => {
108
+ if (result.isFail) {
109
+ if (snd.isNone)
110
+ controller.abort();
111
+ callback(result);
112
+ }
113
+ else if (snd.isNone)
114
+ fst = new Some(result.value);
115
+ else
116
+ callback(new Okay(new Pair(result.value, snd.value)));
117
+ });
118
+ that.execute(controller.signal, (result) => {
119
+ if (result.isFail) {
120
+ if (fst.isNone)
121
+ controller.abort();
122
+ callback(result);
123
+ }
124
+ else if (fst.isNone)
125
+ snd = new Some(result.value);
126
+ else
127
+ callback(new Okay(new Pair(fst.value, result.value)));
128
+ });
129
+ return (reason) => controller.abort(reason);
130
+ });
131
+ }
132
+ andThen(that) {
133
+ return this.and(that).mapOkay((pair) => pair.snd);
134
+ }
135
+ andWhen(that) {
136
+ return this.and(that).mapOkay((pair) => pair.fst);
137
+ }
138
+ or(that) {
139
+ return Task.of((callback) => {
140
+ const controller = new AbortController();
141
+ let fst = None.instance;
142
+ let snd = None.instance;
143
+ this.execute(controller.signal, (result) => {
144
+ if (result.isOkay) {
145
+ if (snd.isNone)
146
+ controller.abort();
147
+ callback(result);
148
+ }
149
+ else if (snd.isNone)
150
+ fst = new Some(result.value);
151
+ else
152
+ callback(new Fail(new Pair(result.value, snd.value)));
153
+ });
154
+ that.execute(controller.signal, (result) => {
155
+ if (result.isOkay) {
156
+ if (fst.isNone)
157
+ controller.abort();
158
+ callback(result);
159
+ }
160
+ else if (fst.isNone)
161
+ snd = new Some(result.value);
162
+ else
163
+ callback(new Fail(new Pair(fst.value, result.value)));
164
+ });
165
+ return (reason) => controller.abort(reason);
166
+ });
167
+ }
168
+ orElse(that) {
169
+ return this.or(that).mapFail((pair) => pair.snd);
170
+ }
171
+ orErst(that) {
172
+ return this.or(that).mapFail((pair) => pair.fst);
173
+ }
174
+ flatMap(okayArrow, failArrow) {
175
+ return new Task((signal, callback) => this.execute(signal, (result) => result.isOkay
176
+ ? okayArrow(result.value).execute(signal, callback)
177
+ : failArrow(result.value).execute(signal, callback)));
178
+ }
179
+ flatMapOkay(arrow) {
180
+ return new Task((signal, callback) => this.execute(signal, (result) => result.isOkay
181
+ ? arrow(result.value).execute(signal, callback)
182
+ : callback(result)));
183
+ }
184
+ flatMapFail(arrow) {
185
+ return new Task((signal, callback) => this.execute(signal, (result) => result.isFail
186
+ ? arrow(result.value).execute(signal, callback)
187
+ : callback(result)));
188
+ }
189
+ flatten() {
190
+ return new Task((signal, callback) => this.execute(signal, (result) => result.value.execute(signal, callback)));
191
+ }
192
+ flattenOkay() {
193
+ return new Task((signal, callback) => this.execute(signal, (result) => result.isOkay
194
+ ? result.value.execute(signal, callback)
195
+ : callback(result)));
196
+ }
197
+ flattenFail() {
198
+ return new Task((signal, callback) => this.execute(signal, (result) => result.isFail
199
+ ? result.value.execute(signal, callback)
200
+ : callback(result)));
201
+ }
202
+ flatMapUntil(okayArrow, failArrow) {
203
+ return new Task((signal, callback) => {
204
+ const trampoline = (task) => {
205
+ let option = new Some(task);
206
+ while (option.isSome) {
207
+ const task = option.value;
208
+ option = None.instance;
209
+ let isAsync = false;
210
+ task.flatMap(okayArrow, failArrow).execute(signal, (value) => {
211
+ const result = value.distribute();
212
+ if (result.isOkay)
213
+ callback(result.value);
214
+ else if (isAsync)
215
+ trampoline(result.value.toTask());
216
+ else
217
+ option = new Some(result.value.toTask());
218
+ });
219
+ isAsync = true;
220
+ }
221
+ };
222
+ trampoline(this);
223
+ });
224
+ }
225
+ flatMapOkayUntil(arrow) {
226
+ return new Task((signal, callback) => {
227
+ const trampoline = (task) => {
228
+ let option = new Some(task);
229
+ while (option.isSome) {
230
+ const task = option.value;
231
+ option = None.instance;
232
+ let isAsync = false;
233
+ task.flatMapOkay(arrow).execute(signal, (value) => {
234
+ const result = value.exchangeFail();
235
+ if (result.isOkay)
236
+ callback(result.value);
237
+ else if (isAsync)
238
+ trampoline(Task.okay(result.value));
239
+ else
240
+ option = new Some(Task.okay(result.value));
241
+ });
242
+ isAsync = true;
243
+ }
244
+ };
245
+ trampoline(this);
246
+ });
247
+ }
248
+ flatMapFailUntil(arrow) {
249
+ return new Task((signal, callback) => {
250
+ const trampoline = (task) => {
251
+ let option = new Some(task);
252
+ while (option.isSome) {
253
+ const task = option.value;
254
+ option = None.instance;
255
+ let isAsync = false;
256
+ task.flatMapFail(arrow).execute(signal, (value) => {
257
+ const result = value.associateLeft();
258
+ if (result.isOkay)
259
+ callback(result.value);
260
+ else if (isAsync)
261
+ trampoline(Task.fail(result.value));
262
+ else
263
+ option = new Some(Task.fail(result.value));
264
+ });
265
+ isAsync = true;
266
+ }
267
+ };
268
+ trampoline(this);
269
+ });
270
+ }
271
+ commute() {
272
+ return new Task((signal, callback) => this.execute(signal, (result) => callback(result.commute())));
273
+ }
274
+ *effectMap(morphism) {
275
+ const value = yield this;
276
+ return morphism(value);
277
+ }
278
+ *effect() {
279
+ const value = yield this;
280
+ return value;
281
+ }
282
+ }
package/lib/text.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { Option } from "./option.js";
2
+ import type { TotalOrder } from "./order.js";
3
+ import type { Ordering } from "./ordering.js";
4
+ import type { Semigroup } from "./semigroup.js";
5
+ export declare class Text implements Semigroup<Text>, TotalOrder<Text> {
6
+ readonly value: string;
7
+ constructor(value: string);
8
+ static of(value: string): Text;
9
+ toString(this: Text): string;
10
+ append(this: Text, that: Text): Text;
11
+ isSame(this: Text, that: Text): boolean;
12
+ isNotSame(this: Text, that: Text): boolean;
13
+ isLess(this: Text, that: Text): boolean;
14
+ isNotLess(this: Text, that: Text): boolean;
15
+ isMore(this: Text, that: Text): boolean;
16
+ isNotMore(this: Text, that: Text): boolean;
17
+ compare(this: Text, that: Text): Option<Ordering>;
18
+ max(this: Text, that: Text): Text;
19
+ min(this: Text, that: Text): Text;
20
+ clamp(this: Text, lower: Text, upper: Text): Text;
21
+ }
package/lib/text.js ADDED
@@ -0,0 +1,50 @@
1
+ import { Some } from "./option.js";
2
+ export class Text {
3
+ value;
4
+ constructor(value) {
5
+ this.value = value;
6
+ }
7
+ static of(value) {
8
+ return new Text(value);
9
+ }
10
+ toString() {
11
+ return `Text(${JSON.stringify(this.value)})`;
12
+ }
13
+ append(that) {
14
+ return new Text(`${this.value}${that.value}`);
15
+ }
16
+ isSame(that) {
17
+ return this.value === that.value;
18
+ }
19
+ isNotSame(that) {
20
+ return this.value !== that.value;
21
+ }
22
+ isLess(that) {
23
+ return this.value < that.value;
24
+ }
25
+ isNotLess(that) {
26
+ return this.value >= that.value;
27
+ }
28
+ isMore(that) {
29
+ return this.value > that.value;
30
+ }
31
+ isNotMore(that) {
32
+ return this.value <= that.value;
33
+ }
34
+ compare(that) {
35
+ if (this.value < that.value)
36
+ return new Some("<");
37
+ if (this.value > that.value)
38
+ return new Some(">");
39
+ return new Some("=");
40
+ }
41
+ max(that) {
42
+ return this.value >= that.value ? this : that;
43
+ }
44
+ min(that) {
45
+ return this.value <= that.value ? this : that;
46
+ }
47
+ clamp(lower, upper) {
48
+ return this.max(lower).min(upper);
49
+ }
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aang",
3
- "version": "2.0.0-alpha.3",
3
+ "version": "2.0.0-alpha.30",
4
4
  "description": "A powerful functional programming library for TypeScript.",
5
5
  "keywords": [
6
6
  "aang",
package/lib/errors.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import { Exception } from "./exceptions.js";
2
- export declare class UnsafeExtractError extends Exception {
3
- constructor(message: string);
4
- }
package/lib/errors.js DELETED
@@ -1,7 +0,0 @@
1
- import { Exception } from "./exceptions.js";
2
- export class UnsafeExtractError extends Exception {
3
- constructor(message) {
4
- super(message);
5
- this.setName("UnsafeExtractError");
6
- }
7
- }