@satoshibits/functional 1.1.0 → 1.1.2

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.
Files changed (130) hide show
  1. package/README.md +28 -145
  2. package/dist/array-utils.d.mts +13 -0
  3. package/dist/array-utils.d.mts.map +1 -1
  4. package/dist/array-utils.mjs +13 -0
  5. package/dist/array-utils.mjs.map +1 -1
  6. package/dist/array-utils.test.d.ts +2 -0
  7. package/dist/array-utils.test.d.ts.map +1 -0
  8. package/dist/array-utils.test.js +256 -0
  9. package/dist/array-utils.test.js.map +1 -0
  10. package/dist/composition.d.mts +13 -0
  11. package/dist/composition.d.mts.map +1 -1
  12. package/dist/composition.mjs +13 -0
  13. package/dist/composition.mjs.map +1 -1
  14. package/dist/composition.test.d.ts +2 -0
  15. package/dist/composition.test.d.ts.map +1 -0
  16. package/dist/composition.test.js +409 -0
  17. package/dist/composition.test.js.map +1 -0
  18. package/dist/integration.test.d.mts +2 -0
  19. package/dist/integration.test.d.mts.map +1 -0
  20. package/dist/integration.test.mjs +486 -0
  21. package/dist/integration.test.mjs.map +1 -0
  22. package/dist/io.d.mts +12 -0
  23. package/dist/io.d.mts.map +1 -1
  24. package/dist/io.mjs +12 -0
  25. package/dist/io.mjs.map +1 -1
  26. package/dist/io.test.d.mts +2 -0
  27. package/dist/io.test.d.mts.map +1 -0
  28. package/dist/io.test.mjs +373 -0
  29. package/dist/io.test.mjs.map +1 -0
  30. package/dist/laws.test.d.mts +2 -0
  31. package/dist/laws.test.d.mts.map +1 -0
  32. package/dist/laws.test.mjs +614 -0
  33. package/dist/laws.test.mjs.map +1 -0
  34. package/dist/object-utils.d.mts +11 -0
  35. package/dist/object-utils.d.mts.map +1 -1
  36. package/dist/object-utils.mjs +11 -0
  37. package/dist/object-utils.mjs.map +1 -1
  38. package/dist/object-utils.test.d.ts +2 -0
  39. package/dist/object-utils.test.d.ts.map +1 -0
  40. package/dist/object-utils.test.js +286 -0
  41. package/dist/object-utils.test.js.map +1 -0
  42. package/dist/option-additions.test.d.mts +2 -0
  43. package/dist/option-additions.test.d.mts.map +1 -0
  44. package/dist/option-additions.test.mjs +325 -0
  45. package/dist/option-additions.test.mjs.map +1 -0
  46. package/dist/option.d.mts +20 -3
  47. package/dist/option.d.mts.map +1 -1
  48. package/dist/option.mjs +20 -3
  49. package/dist/option.mjs.map +1 -1
  50. package/dist/option.test.d.ts +6 -0
  51. package/dist/option.test.d.ts.map +1 -0
  52. package/dist/option.test.js +606 -0
  53. package/dist/option.test.js.map +1 -0
  54. package/dist/performance.d.mts +26 -9
  55. package/dist/performance.d.mts.map +1 -1
  56. package/dist/performance.mjs +26 -9
  57. package/dist/performance.mjs.map +1 -1
  58. package/dist/performance.test.d.ts +2 -0
  59. package/dist/performance.test.d.ts.map +1 -0
  60. package/dist/performance.test.js +424 -0
  61. package/dist/performance.test.js.map +1 -0
  62. package/dist/pipeline.d.mts +12 -0
  63. package/dist/pipeline.d.mts.map +1 -1
  64. package/dist/pipeline.mjs +12 -0
  65. package/dist/pipeline.mjs.map +1 -1
  66. package/dist/pipeline.test.d.ts +2 -0
  67. package/dist/pipeline.test.d.ts.map +1 -0
  68. package/dist/pipeline.test.js +445 -0
  69. package/dist/pipeline.test.js.map +1 -0
  70. package/dist/predicates.d.mts +12 -0
  71. package/dist/predicates.d.mts.map +1 -1
  72. package/dist/predicates.mjs +12 -0
  73. package/dist/predicates.mjs.map +1 -1
  74. package/dist/predicates.test.d.ts +2 -0
  75. package/dist/predicates.test.d.ts.map +1 -0
  76. package/dist/predicates.test.js +375 -0
  77. package/dist/predicates.test.js.map +1 -0
  78. package/dist/reader-result.d.mts +37 -16
  79. package/dist/reader-result.d.mts.map +1 -1
  80. package/dist/reader-result.mjs +37 -16
  81. package/dist/reader-result.mjs.map +1 -1
  82. package/dist/reader-result.test.d.ts +2 -0
  83. package/dist/reader-result.test.d.ts.map +1 -0
  84. package/dist/reader-result.test.js +1259 -0
  85. package/dist/reader-result.test.js.map +1 -0
  86. package/dist/reader.d.mts +12 -0
  87. package/dist/reader.d.mts.map +1 -1
  88. package/dist/reader.mjs +12 -0
  89. package/dist/reader.mjs.map +1 -1
  90. package/dist/reader.test.d.mts +2 -0
  91. package/dist/reader.test.d.mts.map +1 -0
  92. package/dist/reader.test.mjs +288 -0
  93. package/dist/reader.test.mjs.map +1 -0
  94. package/dist/result-additions.test.d.mts +2 -0
  95. package/dist/result-additions.test.d.mts.map +1 -0
  96. package/dist/result-additions.test.mjs +325 -0
  97. package/dist/result-additions.test.mjs.map +1 -0
  98. package/dist/result.d.mts +12 -0
  99. package/dist/result.d.mts.map +1 -1
  100. package/dist/result.mjs +12 -0
  101. package/dist/result.mjs.map +1 -1
  102. package/dist/result.test.d.ts +2 -0
  103. package/dist/result.test.d.ts.map +1 -0
  104. package/dist/result.test.js +453 -0
  105. package/dist/result.test.js.map +1 -0
  106. package/dist/task.d.mts +13 -0
  107. package/dist/task.d.mts.map +1 -1
  108. package/dist/task.mjs +13 -0
  109. package/dist/task.mjs.map +1 -1
  110. package/dist/task.test.d.mts +2 -0
  111. package/dist/task.test.d.mts.map +1 -0
  112. package/dist/task.test.mjs +1006 -0
  113. package/dist/task.test.mjs.map +1 -0
  114. package/dist/types.d.mts +12 -0
  115. package/dist/types.d.mts.map +1 -1
  116. package/dist/types.mjs +12 -0
  117. package/dist/types.mjs.map +1 -1
  118. package/dist/types.test.d.ts +6 -0
  119. package/dist/types.test.d.ts.map +1 -0
  120. package/dist/types.test.js +447 -0
  121. package/dist/types.test.js.map +1 -0
  122. package/dist/validation.d.mts +12 -0
  123. package/dist/validation.d.mts.map +1 -1
  124. package/dist/validation.mjs +12 -0
  125. package/dist/validation.mjs.map +1 -1
  126. package/dist/validation.test.d.ts +2 -0
  127. package/dist/validation.test.d.ts.map +1 -0
  128. package/dist/validation.test.js +518 -0
  129. package/dist/validation.test.js.map +1 -0
  130. package/package.json +77 -13
@@ -0,0 +1,614 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ import { describe, expect, it } from "vitest";
39
+ import { IO } from "./io.mjs";
40
+ import { none, Option, some } from "./option.mjs";
41
+ import { Reader } from "./reader.mjs";
42
+ import { Result } from "./result.mjs";
43
+ import { Task } from "./task.mjs";
44
+ /**
45
+ * Algebraic law tests for functional types.
46
+ * These tests verify that our implementations satisfy the mathematical laws
47
+ * required for functors, monads, and applicatives.
48
+ */
49
+ describe("Algebraic Laws", function () {
50
+ // generic identity function
51
+ var id = function (x) { return x; };
52
+ describe("Task Laws", function () {
53
+ describe("Functor Laws", function () {
54
+ it("identity: map(id) ≅ id", function () { return __awaiter(void 0, void 0, void 0, function () {
55
+ var task, mapped, r1, r2;
56
+ return __generator(this, function (_a) {
57
+ switch (_a.label) {
58
+ case 0:
59
+ task = Task.of(42);
60
+ mapped = Task.map(id)(task);
61
+ return [4 /*yield*/, Task.run(task)];
62
+ case 1:
63
+ r1 = _a.sent();
64
+ return [4 /*yield*/, Task.run(mapped)];
65
+ case 2:
66
+ r2 = _a.sent();
67
+ expect(r1).toEqual(r2);
68
+ return [2 /*return*/];
69
+ }
70
+ });
71
+ }); });
72
+ it("composition: map(g∘f) ≅ map(g)∘map(f)", function () { return __awaiter(void 0, void 0, void 0, function () {
73
+ var task, f, g, r1, r2;
74
+ return __generator(this, function (_a) {
75
+ switch (_a.label) {
76
+ case 0:
77
+ task = Task.of(10);
78
+ f = function (n) { return n * 2; };
79
+ g = function (n) { return n + 1; };
80
+ return [4 /*yield*/, Task.run(Task.map(function (x) { return g(f(x)); })(task))];
81
+ case 1:
82
+ r1 = _a.sent();
83
+ return [4 /*yield*/, Task.run(Task.map(g)(Task.map(f)(task)))];
84
+ case 2:
85
+ r2 = _a.sent();
86
+ expect(r1).toEqual(r2);
87
+ return [2 /*return*/];
88
+ }
89
+ });
90
+ }); });
91
+ });
92
+ describe("Monad Laws", function () {
93
+ it("left identity: chain(f)(of(x)) ≅ f(x)", function () { return __awaiter(void 0, void 0, void 0, function () {
94
+ var x, f, r1, r2;
95
+ return __generator(this, function (_a) {
96
+ switch (_a.label) {
97
+ case 0:
98
+ x = 42;
99
+ f = function (n) { return Task.of(n * 2); };
100
+ return [4 /*yield*/, Task.run(Task.chain(f)(Task.of(x)))];
101
+ case 1:
102
+ r1 = _a.sent();
103
+ return [4 /*yield*/, Task.run(f(x))];
104
+ case 2:
105
+ r2 = _a.sent();
106
+ expect(r1).toEqual(r2);
107
+ return [2 /*return*/];
108
+ }
109
+ });
110
+ }); });
111
+ it("right identity: chain(of)(m) ≅ m", function () { return __awaiter(void 0, void 0, void 0, function () {
112
+ var task, chained, r1, r2;
113
+ return __generator(this, function (_a) {
114
+ switch (_a.label) {
115
+ case 0:
116
+ task = Task.of(42);
117
+ chained = Task.chain(Task.of)(task);
118
+ return [4 /*yield*/, Task.run(task)];
119
+ case 1:
120
+ r1 = _a.sent();
121
+ return [4 /*yield*/, Task.run(chained)];
122
+ case 2:
123
+ r2 = _a.sent();
124
+ expect(r1).toEqual(r2);
125
+ return [2 /*return*/];
126
+ }
127
+ });
128
+ }); });
129
+ it("associativity: chain(g)(chain(f)(m)) ≅ chain(x => chain(g)(f(x)))(m)", function () { return __awaiter(void 0, void 0, void 0, function () {
130
+ var task, f, g, r1, r2;
131
+ return __generator(this, function (_a) {
132
+ switch (_a.label) {
133
+ case 0:
134
+ task = Task.of(10);
135
+ f = function (n) { return Task.of(n * 2); };
136
+ g = function (n) { return Task.of(n + 1); };
137
+ return [4 /*yield*/, Task.run(Task.chain(g)(Task.chain(f)(task)))];
138
+ case 1:
139
+ r1 = _a.sent();
140
+ return [4 /*yield*/, Task.run(Task.chain(function (x) { return Task.chain(g)(f(x)); })(task))];
141
+ case 2:
142
+ r2 = _a.sent();
143
+ expect(r1).toEqual(r2);
144
+ return [2 /*return*/];
145
+ }
146
+ });
147
+ }); });
148
+ });
149
+ describe("Applicative Laws", function () {
150
+ it("identity: ap(of(id))(v) ≅ v", function () { return __awaiter(void 0, void 0, void 0, function () {
151
+ var value, identity, r1, r2;
152
+ return __generator(this, function (_a) {
153
+ switch (_a.label) {
154
+ case 0:
155
+ value = Task.of(42);
156
+ identity = Task.of(id);
157
+ return [4 /*yield*/, Task.run(Task.ap(value)(identity))];
158
+ case 1:
159
+ r1 = _a.sent();
160
+ return [4 /*yield*/, Task.run(value)];
161
+ case 2:
162
+ r2 = _a.sent();
163
+ expect(r1).toEqual(r2);
164
+ return [2 /*return*/];
165
+ }
166
+ });
167
+ }); });
168
+ it("composition: ap(ap(ap(of(compose))(u))(v))(w) ≅ ap(u)(ap(v)(w))", function () { return __awaiter(void 0, void 0, void 0, function () {
169
+ var compose, u, v, w, step1, step2, r1, innerAp, outerAp, r2;
170
+ return __generator(this, function (_a) {
171
+ switch (_a.label) {
172
+ case 0:
173
+ compose = function (g) { return function (f) { return function (x) { return g(f(x)); }; }; };
174
+ u = Task.of(function (n) { return n * 2; });
175
+ v = Task.of(function (n) { return n + 10; });
176
+ w = Task.of(5);
177
+ step1 = Task.ap(u)(Task.of(compose));
178
+ step2 = Task.ap(v)(step1);
179
+ return [4 /*yield*/, Task.run(Task.ap(w)(step2))];
180
+ case 1:
181
+ r1 = _a.sent();
182
+ innerAp = Task.ap(w)(v);
183
+ outerAp = Task.ap(innerAp)(u);
184
+ return [4 /*yield*/, Task.run(outerAp)];
185
+ case 2:
186
+ r2 = _a.sent();
187
+ expect(r1).toEqual(r2);
188
+ return [2 /*return*/];
189
+ }
190
+ });
191
+ }); });
192
+ it("homomorphism: ap(of(x))(of(f)) ≅ of(f(x))", function () { return __awaiter(void 0, void 0, void 0, function () {
193
+ var f, x, r1, r2;
194
+ return __generator(this, function (_a) {
195
+ switch (_a.label) {
196
+ case 0:
197
+ f = function (n) { return n * 2; };
198
+ x = 42;
199
+ return [4 /*yield*/, Task.run(Task.ap(Task.of(x))(Task.of(f)))];
200
+ case 1:
201
+ r1 = _a.sent();
202
+ return [4 /*yield*/, Task.run(Task.of(f(x)))];
203
+ case 2:
204
+ r2 = _a.sent();
205
+ expect(r1).toEqual(r2);
206
+ return [2 /*return*/];
207
+ }
208
+ });
209
+ }); });
210
+ it("interchange: ap(of(y))(u) ≅ ap(u)(of(f => f(y)))", function () { return __awaiter(void 0, void 0, void 0, function () {
211
+ var y, u, r1, r2;
212
+ return __generator(this, function (_a) {
213
+ switch (_a.label) {
214
+ case 0:
215
+ y = 42;
216
+ u = Task.of(function (n) { return n * 2; });
217
+ return [4 /*yield*/, Task.run(Task.ap(Task.of(y))(u))];
218
+ case 1:
219
+ r1 = _a.sent();
220
+ return [4 /*yield*/, Task.run(Task.ap(u)(Task.of(function (f) { return f(y); })))];
221
+ case 2:
222
+ r2 = _a.sent();
223
+ expect(r1).toEqual(r2);
224
+ return [2 /*return*/];
225
+ }
226
+ });
227
+ }); });
228
+ });
229
+ });
230
+ describe("IO Laws", function () {
231
+ describe("Functor Laws", function () {
232
+ it("identity: map(id) ≅ id", function () {
233
+ var io = IO.of(42);
234
+ var mapped = IO.map(id)(io);
235
+ expect(IO.run(io)).toEqual(IO.run(mapped));
236
+ });
237
+ it("composition: map(g∘f) ≅ map(g)∘map(f)", function () {
238
+ var io = IO.of(10);
239
+ var f = function (n) { return n * 2; };
240
+ var g = function (n) { return n + 1; };
241
+ var r1 = IO.run(IO.map(function (x) { return g(f(x)); })(io));
242
+ var r2 = IO.run(IO.map(g)(IO.map(f)(io)));
243
+ expect(r1).toEqual(r2);
244
+ });
245
+ });
246
+ describe("Applicative Laws", function () {
247
+ it("identity: ap(of(id))(v) ≅ v", function () {
248
+ var value = IO.of(42);
249
+ var identity = IO.of(id);
250
+ var r1 = IO.run(IO.ap(value)(identity));
251
+ var r2 = IO.run(value);
252
+ expect(r1).toEqual(r2);
253
+ });
254
+ it("composition: ap(ap(ap(of(compose))(u))(v))(w) ≅ ap(u)(ap(v)(w))", function () {
255
+ var compose = function (g) { return function (f) { return function (x) { return g(f(x)); }; }; };
256
+ var u = IO.of(function (n) { return n * 2; });
257
+ var v = IO.of(function (n) { return n + 10; });
258
+ var w = IO.of(5);
259
+ // Left side: compose via lifted compose function
260
+ var step1 = IO.ap(u)(IO.of(compose));
261
+ var step2 = IO.ap(v)(step1);
262
+ var r1 = IO.run(IO.ap(w)(step2));
263
+ // Right side: direct composition
264
+ var innerAp = IO.ap(w)(v);
265
+ var outerAp = IO.ap(innerAp)(u);
266
+ var r2 = IO.run(outerAp);
267
+ expect(r1).toEqual(r2);
268
+ });
269
+ it("homomorphism: ap(of(x))(of(f)) ≅ of(f(x))", function () {
270
+ var f = function (n) { return n * 2; };
271
+ var x = 42;
272
+ var r1 = IO.run(IO.ap(IO.of(x))(IO.of(f)));
273
+ var r2 = IO.run(IO.of(f(x)));
274
+ expect(r1).toEqual(r2);
275
+ });
276
+ it("interchange: ap(of(y))(u) ≅ ap(u)(of(f => f(y)))", function () {
277
+ var y = 42;
278
+ var u = IO.of(function (n) { return n * 2; });
279
+ var r1 = IO.run(IO.ap(IO.of(y))(u));
280
+ var r2 = IO.run(IO.ap(u)(IO.of(function (f) { return f(y); })));
281
+ expect(r1).toEqual(r2);
282
+ });
283
+ });
284
+ describe("Monad Laws", function () {
285
+ it("left identity: chain(f)(of(x)) ≅ f(x)", function () {
286
+ var x = 42;
287
+ var f = function (n) { return IO.of(n * 2); };
288
+ var r1 = IO.run(IO.chain(f)(IO.of(x)));
289
+ var r2 = IO.run(f(x));
290
+ expect(r1).toEqual(r2);
291
+ });
292
+ it("right identity: chain(of)(m) ≅ m", function () {
293
+ var io = IO.of(42);
294
+ var chained = IO.chain(IO.of)(io);
295
+ expect(IO.run(io)).toEqual(IO.run(chained));
296
+ });
297
+ it("associativity: chain(g)(chain(f)(m)) ≅ chain(x => chain(g)(f(x)))(m)", function () {
298
+ var io = IO.of(10);
299
+ var f = function (n) { return IO.of(n * 2); };
300
+ var g = function (n) { return IO.of(n + 1); };
301
+ var r1 = IO.run(IO.chain(g)(IO.chain(f)(io)));
302
+ var r2 = IO.run(IO.chain(function (x) { return IO.chain(g)(f(x)); })(io));
303
+ expect(r1).toEqual(r2);
304
+ });
305
+ });
306
+ });
307
+ describe("Reader Laws", function () {
308
+ var testEnv = { multiplier: 2, offset: 10 };
309
+ describe("Functor Laws", function () {
310
+ it("identity: map(id) ≅ id", function () {
311
+ var reader = Reader.of(42);
312
+ var mapped = Reader.map(id)(reader);
313
+ expect(Reader.run(testEnv)(reader)).toEqual(Reader.run(testEnv)(mapped));
314
+ });
315
+ it("composition: map(g∘f) ≅ map(g)∘map(f)", function () {
316
+ var reader = Reader.asks(function (env) { return env.multiplier; });
317
+ var f = function (n) { return n * 2; };
318
+ var g = function (n) { return n + 1; };
319
+ var r1 = Reader.run(testEnv)(Reader.map(function (x) { return g(f(x)); })(reader));
320
+ var r2 = Reader.run(testEnv)(Reader.map(g)(Reader.map(f)(reader)));
321
+ expect(r1).toEqual(r2);
322
+ });
323
+ });
324
+ describe("Applicative Laws", function () {
325
+ it("identity: ap(of(id))(v) ≅ v", function () {
326
+ var value = Reader.of(42);
327
+ var identity = Reader.of(id);
328
+ var r1 = Reader.run(testEnv)(Reader.ap(value)(identity));
329
+ var r2 = Reader.run(testEnv)(value);
330
+ expect(r1).toEqual(r2);
331
+ });
332
+ it("composition: ap(ap(ap(of(compose))(u))(v))(w) ≅ ap(u)(ap(v)(w))", function () {
333
+ var compose = function (g) { return function (f) { return function (x) { return g(f(x)); }; }; };
334
+ var u = Reader.of(function (n) { return n * 2; });
335
+ var v = Reader.of(function (n) { return n + 10; });
336
+ var w = Reader.of(5);
337
+ // Left side: compose via lifted compose function
338
+ var composeReader = Reader.of(compose);
339
+ var applyU = Reader.ap(u)(composeReader);
340
+ var applyV = Reader.ap(v)(applyU);
341
+ var r1 = Reader.run(testEnv)(Reader.ap(w)(applyV));
342
+ // Right side: direct composition
343
+ var r2 = Reader.run(testEnv)(Reader.ap(Reader.ap(w)(v))(u));
344
+ expect(r1).toEqual(r2);
345
+ });
346
+ it("homomorphism: ap(of(x))(of(f)) ≅ of(f(x))", function () {
347
+ var f = function (n) { return n * 2; };
348
+ var x = 42;
349
+ var r1 = Reader.run(testEnv)(Reader.ap(Reader.of(x))(Reader.of(f)));
350
+ var r2 = Reader.run(testEnv)(Reader.of(f(x)));
351
+ expect(r1).toEqual(r2);
352
+ });
353
+ it("interchange: ap(of(y))(u) ≅ ap(u)(of(f => f(y)))", function () {
354
+ var y = 42;
355
+ var u = Reader.of(function (n) { return n * 2; });
356
+ var r1 = Reader.run(testEnv)(Reader.ap(Reader.of(y))(u));
357
+ var r2 = Reader.run(testEnv)(Reader.ap(u)(Reader.of(function (f) { return f(y); })));
358
+ expect(r1).toEqual(r2);
359
+ });
360
+ });
361
+ describe("Monad Laws", function () {
362
+ it("left identity: chain(f)(of(x)) ≅ f(x)", function () {
363
+ var x = 42;
364
+ var f = function (n) {
365
+ return Reader.asks(function (env) { return n * env.multiplier; });
366
+ };
367
+ var r1 = Reader.run(testEnv)(Reader.chain(f)(Reader.of(x)));
368
+ var r2 = Reader.run(testEnv)(f(x));
369
+ expect(r1).toEqual(r2);
370
+ });
371
+ it("right identity: chain(of)(m) ≅ m", function () {
372
+ var reader = Reader.asks(function (env) { return env.offset; });
373
+ var chained = Reader.chain(Reader.of)(reader);
374
+ expect(Reader.run(testEnv)(reader)).toEqual(Reader.run(testEnv)(chained));
375
+ });
376
+ it("associativity: chain(g)(chain(f)(m)) ≅ chain(x => chain(g)(f(x)))(m)", function () {
377
+ var reader = Reader.of(10);
378
+ var f = function (n) {
379
+ return Reader.asks(function (env) { return n * env.multiplier; });
380
+ };
381
+ var g = function (n) {
382
+ return Reader.asks(function (env) { return n + env.offset; });
383
+ };
384
+ var r1 = Reader.run(testEnv)(Reader.chain(g)(Reader.chain(f)(reader)));
385
+ var r2 = Reader.run(testEnv)(Reader.chain(function (x) { return Reader.chain(g)(f(x)); })(reader));
386
+ expect(r1).toEqual(r2);
387
+ });
388
+ });
389
+ describe("Reader-specific Laws", function () {
390
+ it("ask law: run(env)(ask) ≅ env", function () {
391
+ var reader = Reader.ask();
392
+ expect(Reader.run(testEnv)(reader)).toEqual(testEnv);
393
+ });
394
+ it("asks law: run(env)(asks(f)) ≅ f(env)", function () {
395
+ var f = function (env) { return env.multiplier * env.offset; };
396
+ var reader = Reader.asks(f);
397
+ expect(Reader.run(testEnv)(reader)).toEqual(f(testEnv));
398
+ });
399
+ it("local law: run(env)(local(f)(r)) ≅ run(f(env))(r)", function () {
400
+ var outerEnv = { inner: testEnv };
401
+ var reader = Reader.asks(function (env) { return env.multiplier; });
402
+ var f = function (outer) { return outer.inner; };
403
+ var r1 = Reader.run(outerEnv)(Reader.local(f)(reader));
404
+ var r2 = Reader.run(f(outerEnv))(reader);
405
+ expect(r1).toEqual(r2);
406
+ });
407
+ });
408
+ });
409
+ describe("Result Laws", function () {
410
+ describe("Functor Laws", function () {
411
+ it("identity: map(id) ≅ id", function () {
412
+ var ok = Result.ok(42);
413
+ var err = Result.err("error");
414
+ expect(Result.map(id)(ok)).toEqual(ok);
415
+ expect(Result.map(id)(err)).toEqual(err);
416
+ });
417
+ it("composition: map(g∘f) ≅ map(g)∘map(f)", function () {
418
+ var result = Result.ok(10);
419
+ var f = function (n) { return n * 2; };
420
+ var g = function (n) { return n + 1; };
421
+ var r1 = Result.map(function (x) { return g(f(x)); })(result);
422
+ var r2 = Result.map(g)(Result.map(f)(result));
423
+ expect(r1).toEqual(r2);
424
+ });
425
+ });
426
+ describe("Applicative Laws", function () {
427
+ it("identity: ap(of(id))(v) ≅ v", function () {
428
+ var value = Result.ok(42);
429
+ var identity = Result.ok(id);
430
+ var r1 = Result.ap(value)(identity);
431
+ var r2 = value;
432
+ expect(r1).toEqual(r2);
433
+ });
434
+ it("composition: ap(ap(ap(of(compose))(u))(v))(w) ≅ ap(u)(ap(v)(w))", function () {
435
+ var compose = function (g) { return function (f) { return function (x) { return g(f(x)); }; }; };
436
+ var u = Result.ok(function (n) { return n * 2; });
437
+ var v = Result.ok(function (n) { return n + 10; });
438
+ var w = Result.ok(5);
439
+ // Left side: compose via lifted compose function
440
+ var step1 = Result.ap(u)(Result.ok(compose));
441
+ var step2 = Result.ap(v)(step1);
442
+ var r1 = Result.ap(w)(step2);
443
+ // Right side: direct composition
444
+ var innerAp = Result.ap(w)(v);
445
+ var outerAp = Result.ap(innerAp)(u);
446
+ var r2 = outerAp;
447
+ expect(r1).toEqual(r2);
448
+ });
449
+ it("homomorphism: ap(of(x))(of(f)) ≅ of(f(x))", function () {
450
+ var f = function (n) { return n * 2; };
451
+ var x = 42;
452
+ var r1 = Result.ap(Result.ok(x))(Result.ok(f));
453
+ var r2 = Result.ok(f(x));
454
+ expect(r1).toEqual(r2);
455
+ });
456
+ it("interchange: ap(of(y))(u) ≅ ap(u)(of(f => f(y)))", function () {
457
+ var y = 42;
458
+ var u = Result.ok(function (n) { return n * 2; });
459
+ var r1 = Result.ap(Result.ok(y))(u);
460
+ var r2 = Result.ap(u)(Result.ok(function (f) { return f(y); }));
461
+ expect(r1).toEqual(r2);
462
+ });
463
+ });
464
+ describe("Monad Laws", function () {
465
+ it("left identity: chain(f)(of(x)) ≅ f(x)", function () {
466
+ var x = 42;
467
+ var f = function (n) {
468
+ return n > 0 ? Result.ok(n * 2) : Result.err("negative");
469
+ };
470
+ var r1 = Result.flatMap(f)(Result.ok(x));
471
+ var r2 = f(x);
472
+ expect(r1).toEqual(r2);
473
+ });
474
+ it("right identity: chain(of)(m) ≅ m", function () {
475
+ var result = Result.ok(42);
476
+ var chained = Result.flatMap(Result.ok)(result);
477
+ expect(result).toEqual(chained);
478
+ });
479
+ it("associativity: chain(g)(chain(f)(m)) ≅ chain(x => chain(g)(f(x)))(m)", function () {
480
+ var result = Result.ok(10);
481
+ var f = function (n) { return Result.ok(n * 2); };
482
+ var g = function (n) { return Result.ok(n + 1); };
483
+ var r1 = Result.flatMap(g)(Result.flatMap(f)(result));
484
+ var r2 = Result.flatMap(function (x) { return Result.flatMap(g)(f(x)); })(result);
485
+ expect(r1).toEqual(r2);
486
+ });
487
+ });
488
+ });
489
+ describe("Option Laws", function () {
490
+ describe("Functor Laws", function () {
491
+ it("identity: map(id) ≅ id", function () {
492
+ var someVal = some(42);
493
+ var noneVal = none();
494
+ expect(Option.map(id)(someVal)).toEqual(someVal);
495
+ expect(Option.map(id)(noneVal)).toEqual(noneVal);
496
+ });
497
+ it("composition: map(g∘f) ≅ map(g)∘map(f)", function () {
498
+ var option = some(10);
499
+ var f = function (n) { return n * 2; };
500
+ var g = function (n) { return n + 1; };
501
+ var r1 = Option.map(function (x) { return g(f(x)); })(option);
502
+ var r2 = Option.map(g)(Option.map(f)(option));
503
+ expect(r1).toEqual(r2);
504
+ });
505
+ });
506
+ describe("Applicative Laws", function () {
507
+ it("identity: ap(of(id))(v) ≅ v", function () {
508
+ var value = some(42);
509
+ var identity = some(id);
510
+ var r1 = Option.ap(value)(identity);
511
+ var r2 = value;
512
+ expect(r1).toEqual(r2);
513
+ });
514
+ it("composition: ap(ap(ap(of(compose))(u))(v))(w) ≅ ap(u)(ap(v)(w))", function () {
515
+ var compose = function (g) { return function (f) { return function (x) { return g(f(x)); }; }; };
516
+ var u = some(function (n) { return n * 2; });
517
+ var v = some(function (n) { return n + 10; });
518
+ var w = some(5);
519
+ // Left side: compose via lifted compose function
520
+ var step1 = Option.ap(u)(some(compose));
521
+ var step2 = Option.ap(v)(step1);
522
+ var r1 = Option.ap(w)(step2);
523
+ // Right side: direct composition
524
+ var innerAp = Option.ap(w)(v);
525
+ var outerAp = Option.ap(innerAp)(u);
526
+ var r2 = outerAp;
527
+ expect(r1).toEqual(r2);
528
+ });
529
+ it("homomorphism: ap(of(x))(of(f)) ≅ of(f(x))", function () {
530
+ var f = function (n) { return n * 2; };
531
+ var x = 42;
532
+ var r1 = Option.ap(some(x))(some(f));
533
+ var r2 = some(f(x));
534
+ expect(r1).toEqual(r2);
535
+ });
536
+ it("interchange: ap(of(y))(u) ≅ ap(u)(of(f => f(y)))", function () {
537
+ var y = 42;
538
+ var u = some(function (n) { return n * 2; });
539
+ var r1 = Option.ap(some(y))(u);
540
+ var r2 = Option.ap(u)(some(function (f) { return f(y); }));
541
+ expect(r1).toEqual(r2);
542
+ });
543
+ });
544
+ describe("Monad Laws", function () {
545
+ it("left identity: chain(f)(of(x)) ≅ f(x)", function () {
546
+ var x = 42;
547
+ var f = function (n) { return (n > 0 ? some(n * 2) : none()); };
548
+ var r1 = Option.flatMap(f)(some(x));
549
+ var r2 = f(x);
550
+ expect(r1).toEqual(r2);
551
+ });
552
+ it("right identity: chain(of)(m) ≅ m", function () {
553
+ var option = some(42);
554
+ var chained = Option.flatMap(some)(option);
555
+ expect(option).toEqual(chained);
556
+ });
557
+ it("associativity: chain(g)(chain(f)(m)) ≅ chain(x => chain(g)(f(x)))(m)", function () {
558
+ var option = some(10);
559
+ var f = function (n) { return some(n * 2); };
560
+ var g = function (n) { return some(n + 1); };
561
+ var r1 = Option.flatMap(g)(Option.flatMap(f)(option));
562
+ var r2 = Option.flatMap(function (x) { return Option.flatMap(g)(f(x)); })(option);
563
+ expect(r1).toEqual(r2);
564
+ });
565
+ });
566
+ });
567
+ describe("Cross-type Law Consistency", function () {
568
+ it("all types should handle identity consistently", function () { return __awaiter(void 0, void 0, void 0, function () {
569
+ var value, _a;
570
+ return __generator(this, function (_b) {
571
+ switch (_b.label) {
572
+ case 0:
573
+ value = 42;
574
+ // all should preserve the value through identity
575
+ _a = expect;
576
+ return [4 /*yield*/, Task.run(Task.map(id)(Task.of(value)))];
577
+ case 1:
578
+ // all should preserve the value through identity
579
+ _a.apply(void 0, [_b.sent()]).toBe(value);
580
+ expect(IO.run(IO.map(id)(IO.of(value)))).toBe(value);
581
+ expect(Reader.run({})(Reader.map(id)(Reader.of(value)))).toBe(value);
582
+ expect(Result.map(id)(Result.ok(value))).toEqual(Result.ok(value));
583
+ expect(Option.map(id)(some(value))).toEqual(some(value));
584
+ return [2 /*return*/];
585
+ }
586
+ });
587
+ }); });
588
+ it("all types should handle composition consistently", function () { return __awaiter(void 0, void 0, void 0, function () {
589
+ var f, g, compose, value, expected, _a;
590
+ return __generator(this, function (_b) {
591
+ switch (_b.label) {
592
+ case 0:
593
+ f = function (n) { return n * 2; };
594
+ g = function (n) { return n + 1; };
595
+ compose = function (x) { return g(f(x)); };
596
+ value = 10;
597
+ expected = 21;
598
+ // all should produce the same result
599
+ _a = expect;
600
+ return [4 /*yield*/, Task.run(Task.map(compose)(Task.of(value)))];
601
+ case 1:
602
+ // all should produce the same result
603
+ _a.apply(void 0, [_b.sent()]).toBe(expected);
604
+ expect(IO.run(IO.map(compose)(IO.of(value)))).toBe(expected);
605
+ expect(Reader.run({})(Reader.map(compose)(Reader.of(value)))).toBe(expected);
606
+ expect(Result.map(compose)(Result.ok(value))).toEqual(Result.ok(expected));
607
+ expect(Option.map(compose)(some(value))).toEqual(some(expected));
608
+ return [2 /*return*/];
609
+ }
610
+ });
611
+ }); });
612
+ });
613
+ });
614
+ //# sourceMappingURL=laws.test.mjs.map