@satoshibits/functional 1.0.3 → 1.1.0

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/dist/io.d.mts ADDED
@@ -0,0 +1,326 @@
1
+ /**
2
+ * @module io
3
+ * @description IO represents a synchronous computation that may have side effects.
4
+ * An IO is a thunk (a function with no arguments) that performs a computation when called.
5
+ * This provides a way to make side effects referentially transparent by wrapping them
6
+ * in a function, delaying their execution until explicitly requested.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { IO } from './io.mts';
11
+ *
12
+ * // basic usage
13
+ * const getCurrentTime: IO<number> = () => Date.now();
14
+ * const randomNumber: IO<number> = () => Math.random();
15
+ *
16
+ * // composing IO operations
17
+ * const program = IO.chain((time: number) =>
18
+ * IO.map((rand: number) => `Time: ${time}, Random: ${rand}`)(
19
+ * randomNumber
20
+ * )
21
+ * )(getCurrentTime);
22
+ *
23
+ * // running IO
24
+ * const result = IO.run(program);
25
+ * ```
26
+ *
27
+ * @category Core
28
+ * @since 2025-09-18
29
+ */
30
+ /**
31
+ * IO type representing a synchronous computation that may have side effects.
32
+ * @description An IO is a function that takes no arguments and returns a value.
33
+ * The computation is lazy - it doesn't execute until explicitly run.
34
+ *
35
+ * @template A - The type of the value the IO will produce
36
+ *
37
+ * @category Types
38
+ * @example
39
+ * ```typescript
40
+ * // Simple IO
41
+ * const log: IO<void> = () => console.log('Hello');
42
+ *
43
+ * // IO returning a value
44
+ * const random: IO<number> = () => Math.random();
45
+ *
46
+ * // IO reading from environment
47
+ * const getEnv: IO<string | undefined> = () => process.env.HOME;
48
+ * ```
49
+ *
50
+ * @since 2025-09-18
51
+ */
52
+ export type IO<A> = () => A;
53
+ /**
54
+ * IO utility functions for working with IO types.
55
+ * @description Provides a functional API for creating, transforming, and composing IOs.
56
+ * All functions are curried to support functional composition and partial application.
57
+ *
58
+ * @category Utilities
59
+ * @since 2025-09-18
60
+ */
61
+ export declare const IO: {
62
+ /**
63
+ * Creates an IO that returns the given value.
64
+ * @description Factory function for creating IOs from values. The resulting
65
+ * IO will always return the provided value when run.
66
+ *
67
+ * @template A - The type of the value
68
+ * @param {A} value - The value to wrap in an IO
69
+ * @returns {IO<A>} An IO that returns the value
70
+ *
71
+ * @category Constructors
72
+ * @example
73
+ * ```typescript
74
+ * const io = IO.of(42);
75
+ * IO.run(io); // => 42
76
+ *
77
+ * // Useful for starting chains
78
+ * const result = IO.run(
79
+ * IO.chain((n: number) => IO.of(n * 2))(
80
+ * IO.of(21)
81
+ * )
82
+ * ); // => 42
83
+ * ```
84
+ *
85
+ * @since 2025-09-18
86
+ */
87
+ of: <A>(value: A) => IO<A>;
88
+ /**
89
+ * Transforms the value inside an IO using the given function.
90
+ * @description Applies a pure function to the value produced by an IO,
91
+ * creating a new IO with the transformed value. This is the functor
92
+ * map operation for IO types.
93
+ *
94
+ * @template A - The input type
95
+ * @template B - The output type
96
+ * @param {function(A): B} f - Function to transform the value
97
+ * @returns {function(IO<A>): IO<B>} A function that transforms IOs
98
+ *
99
+ * @category Transformations
100
+ * @example
101
+ * ```typescript
102
+ * const double = IO.map((n: number) => n * 2);
103
+ * const io = IO.of(21);
104
+ * const doubled = double(io);
105
+ * IO.run(doubled); // => 42
106
+ *
107
+ * // With side effects
108
+ * const random = () => Math.random();
109
+ * const percent = IO.map((n: number) => Math.round(n * 100))(random);
110
+ * IO.run(percent); // => random number 0-100
111
+ * ```
112
+ *
113
+ * @since 2025-09-18
114
+ */
115
+ map: <A, B>(f: (value: A) => B) => (io: IO<A>) => IO<B>;
116
+ /**
117
+ * Chains IO-returning operations.
118
+ * @description Sequences two IOs where the second depends on the result
119
+ * of the first. This is the monadic bind operation for IO types.
120
+ *
121
+ * @template A - The input type
122
+ * @template B - The output type
123
+ * @param {function(A): IO<B>} f - Function that returns a new IO
124
+ * @returns {function(IO<A>): IO<B>} A function that chains IOs
125
+ *
126
+ * @category Combinators
127
+ * @example
128
+ * ```typescript
129
+ * const readLine: IO<string> = () => prompt('Enter text:') || '';
130
+ * const toUpper = (s: string): IO<string> => IO.of(s.toUpperCase());
131
+ *
132
+ * const program = IO.chain(toUpper)(readLine);
133
+ * IO.run(program); // prompts user, returns uppercase input
134
+ * ```
135
+ *
136
+ * @since 2025-09-18
137
+ */
138
+ chain: <A, B>(f: (value: A) => IO<B>) => (io: IO<A>) => IO<B>;
139
+ /**
140
+ * Alias for chain to match fp-ts naming.
141
+ * @description See {@link chain} for details.
142
+ *
143
+ * @category Combinators
144
+ * @since 2025-09-18
145
+ */
146
+ flatMap: <A, B>(f: (value: A) => IO<B>) => (io: IO<A>) => IO<B>;
147
+ /**
148
+ * Applies an IO of a function to an IO of a value.
149
+ * @description Enables applying functions wrapped in IOs to values wrapped
150
+ * in IOs. This is the applicative apply operation for IO types.
151
+ *
152
+ * @template A - The input type
153
+ * @template B - The output type
154
+ * @param {IO<A>} ioValue - IO containing a value
155
+ * @returns {function(IO<function(A): B>): IO<B>} A function that applies IO functions
156
+ *
157
+ * @category Combinators
158
+ * @example
159
+ * ```typescript
160
+ * const add = (a: number) => (b: number) => a + b;
161
+ * const ioAdd = IO.of(add);
162
+ * const io5 = IO.of(5);
163
+ * const io3 = IO.of(3);
164
+ *
165
+ * const result = IO.run(
166
+ * IO.ap(io3)(
167
+ * IO.ap(io5)(
168
+ * IO.map(add)(IO.of(10))
169
+ * )
170
+ * )
171
+ * ); // => 18
172
+ * ```
173
+ *
174
+ * @since 2025-09-18
175
+ */
176
+ ap: <A, B>(ioValue: IO<A>) => (ioFn: IO<(a: A) => B>) => IO<B>;
177
+ /**
178
+ * Runs an IO to completion and returns its value.
179
+ * @description Executes an IO, triggering the computation and returning
180
+ * the result. This is where side effects actually occur.
181
+ *
182
+ * @template A - The type of the value
183
+ * @param {IO<A>} io - The IO to run
184
+ * @returns {A} The result of running the IO
185
+ *
186
+ * @category Execution
187
+ * @example
188
+ * ```typescript
189
+ * const io = IO.of(42);
190
+ * const result = IO.run(io); // => 42
191
+ *
192
+ * const sideEffect = () => {
193
+ * console.log('Side effect!');
194
+ * return 'done';
195
+ * };
196
+ * IO.run(sideEffect); // logs "Side effect!", returns 'done'
197
+ * ```
198
+ *
199
+ * @since 2025-09-18
200
+ */
201
+ run: <A>(io: IO<A>) => A;
202
+ /**
203
+ * Converts an array of IOs into an IO of an array.
204
+ * @description Sequences multiple IOs, running them in order and collecting
205
+ * their results.
206
+ *
207
+ * @template A - The type of values in the IOs
208
+ * @param {IO<A>[]} ios - Array of IOs to sequence
209
+ * @returns {IO<A[]>} An IO containing an array of results
210
+ *
211
+ * @category Combinators
212
+ * @example
213
+ * ```typescript
214
+ * const ios = [
215
+ * IO.of(1),
216
+ * IO.of(2),
217
+ * IO.of(3)
218
+ * ];
219
+ * const combined = IO.sequence(ios);
220
+ * IO.run(combined); // => [1, 2, 3]
221
+ * ```
222
+ *
223
+ * @since 2025-09-18
224
+ */
225
+ sequence: <A>(ios: IO<A>[]) => IO<A[]>;
226
+ /**
227
+ * Maps a function returning an IO over an array and sequences the results.
228
+ * @description Applies an IO-returning function to each element of an array
229
+ * and runs all resulting IOs in sequence.
230
+ *
231
+ * @template A - The input type
232
+ * @template B - The output type
233
+ * @param {function(A): IO<B>} f - Function that returns an IO
234
+ * @returns {function(A[]): IO<B[]>} A function that traverses arrays with IOs
235
+ *
236
+ * @category Combinators
237
+ * @example
238
+ * ```typescript
239
+ * const log = (msg: string): IO<string> => () => {
240
+ * console.log(msg);
241
+ * return msg;
242
+ * };
243
+ *
244
+ * const logAll = IO.traverse(log);
245
+ * const messages = IO.run(
246
+ * logAll(['Hello', 'World'])
247
+ * ); // logs each message, returns ['Hello', 'World']
248
+ * ```
249
+ *
250
+ * @since 2025-09-18
251
+ */
252
+ traverse: <A, B>(f: (a: A) => IO<B>) => (as: A[]) => IO<B[]>;
253
+ /**
254
+ * Combines the results of a tuple of IOs into an IO of a tuple.
255
+ * @description Takes multiple IOs and returns an IO containing a tuple
256
+ * of their results.
257
+ *
258
+ * @template T - Tuple type of IOs
259
+ * @param {...T} ios - IOs to combine
260
+ * @returns {IO<{ [K in keyof T]: T[K] extends IO<infer U> ? U : never }>} IO of tuple
261
+ *
262
+ * @category Combinators
263
+ * @example
264
+ * ```typescript
265
+ * const io1 = IO.of(1);
266
+ * const io2 = IO.of('hello');
267
+ * const io3 = IO.of(true);
268
+ *
269
+ * const combined = IO.sequenceT(io1, io2, io3);
270
+ * IO.run(combined); // => [1, 'hello', true]
271
+ * ```
272
+ *
273
+ * @since 2025-09-18
274
+ */
275
+ sequenceT: <T extends readonly IO<unknown>[]>(...ios: T) => IO<{ [K in keyof T]: T[K] extends IO<infer U> ? U : never; }>;
276
+ /**
277
+ * Combines the results of a record of IOs into an IO of a record.
278
+ * @description Takes an object with IO values and returns an IO containing
279
+ * an object with the results.
280
+ *
281
+ * @template R - Record type with IO values
282
+ * @param {R} ios - Record of IOs to combine
283
+ * @returns {IO<{ [K in keyof R]: R[K] extends IO<infer U> ? U : never }>} IO of record
284
+ *
285
+ * @category Combinators
286
+ * @example
287
+ * ```typescript
288
+ * const ios = {
289
+ * user: IO.of({ name: 'Alice' }),
290
+ * count: IO.of(42),
291
+ * enabled: IO.of(true)
292
+ * };
293
+ *
294
+ * const combined = IO.sequenceS(ios);
295
+ * IO.run(combined);
296
+ * // => { user: { name: 'Alice' }, count: 42, enabled: true }
297
+ * ```
298
+ *
299
+ * @since 2025-09-18
300
+ */
301
+ sequenceS: <R extends Record<string, IO<unknown>>>(ios: R) => IO<{ [K in keyof R]: R[K] extends IO<infer U> ? U : never; }>;
302
+ /**
303
+ * Executes an IO for its side effects, discarding the result.
304
+ * @description Runs an IO but returns the original value, useful for IOs
305
+ * that perform side effects where the result isn't needed.
306
+ *
307
+ * @template A - The type of the value
308
+ * @param {function(A): IO<unknown>} f - Function that returns an IO (result discarded)
309
+ * @returns {function(IO<A>): IO<A>} A function that executes side effects
310
+ *
311
+ * @category Combinators
312
+ * @example
313
+ * ```typescript
314
+ * const log = (msg: string): IO<void> => () => console.log(msg);
315
+ *
316
+ * const io = IO.chainFirst((n: number) => log(`Got: ${n}`))(
317
+ * IO.of(42)
318
+ * );
319
+ * IO.run(io); // logs "Got: 42", returns 42
320
+ * ```
321
+ *
322
+ * @since 2025-09-18
323
+ */
324
+ chainFirst: <A>(f: (a: A) => IO<unknown>) => (io: IO<A>) => IO<A>;
325
+ };
326
+ //# sourceMappingURL=io.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io.d.mts","sourceRoot":"","sources":["../src/io.mts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,EAAE;IACb;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;SAEA,CAAC,SAAU,CAAC,KAAG,EAAE,CAAC,CAAC,CAAC;IAIvB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;UAEA,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,UACpB,EAAE,CAAC,CAAC,CAAC,KAAG,EAAE,CAAC,CAAC,CAAC;IAIpB;;;;;;;;;;;;;;;;;;;;;OAqBG;YAEA,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,UACxB,EAAE,CAAC,CAAC,CAAC,KAAG,EAAE,CAAC,CAAC,CAAC;IAIpB;;;;;;OAMG;cAEA,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,UACxB,EAAE,CAAC,CAAC,CAAC,KAAG,EAAE,CAAC,CAAC,CAAC;IAIpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;SAEA,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,YACd,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAG,EAAE,CAAC,CAAC,CAAC;IAIhC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;UACG,CAAC,MAAO,EAAE,CAAC,CAAC,CAAC,KAAG,CAAC;IAEvB;;;;;;;;;;;;;;;;;;;;;;OAsBG;eAEA,CAAC,OAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,KAAG,EAAE,CAAC,CAAC,EAAE,CAAC;IAI7B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;eAEA,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,UACpB,CAAC,EAAE,KAAG,EAAE,CAAC,CAAC,EAAE,CAAC;IAGpB;;;;;;;;;;;;;;;;;;;;;OAqBG;gBAEA,CAAC,SAAS,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,UACvB,CAAC,KACR,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,GAAE,CAAC;IAMjE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;gBAEA,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,OAC/B,CAAC,KACL,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,GAAE,CAAC;IAajE;;;;;;;;;;;;;;;;;;;;;OAqBG;iBAEA,CAAC,KAAM,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,UACxB,EAAE,CAAC,CAAC,CAAC,KAAG,EAAE,CAAC,CAAC,CAAC;CAMrB,CAAC"}
package/dist/io.mjs ADDED
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ /**
3
+ * @module io
4
+ * @description IO represents a synchronous computation that may have side effects.
5
+ * An IO is a thunk (a function with no arguments) that performs a computation when called.
6
+ * This provides a way to make side effects referentially transparent by wrapping them
7
+ * in a function, delaying their execution until explicitly requested.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { IO } from './io.mts';
12
+ *
13
+ * // basic usage
14
+ * const getCurrentTime: IO<number> = () => Date.now();
15
+ * const randomNumber: IO<number> = () => Math.random();
16
+ *
17
+ * // composing IO operations
18
+ * const program = IO.chain((time: number) =>
19
+ * IO.map((rand: number) => `Time: ${time}, Random: ${rand}`)(
20
+ * randomNumber
21
+ * )
22
+ * )(getCurrentTime);
23
+ *
24
+ * // running IO
25
+ * const result = IO.run(program);
26
+ * ```
27
+ *
28
+ * @category Core
29
+ * @since 2025-09-18
30
+ */
31
+ var __assign = (this && this.__assign) || function () {
32
+ __assign = Object.assign || function(t) {
33
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
34
+ s = arguments[i];
35
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
36
+ t[p] = s[p];
37
+ }
38
+ return t;
39
+ };
40
+ return __assign.apply(this, arguments);
41
+ };
42
+ /**
43
+ * IO utility functions for working with IO types.
44
+ * @description Provides a functional API for creating, transforming, and composing IOs.
45
+ * All functions are curried to support functional composition and partial application.
46
+ *
47
+ * @category Utilities
48
+ * @since 2025-09-18
49
+ */
50
+ export var IO = {
51
+ /**
52
+ * Creates an IO that returns the given value.
53
+ * @description Factory function for creating IOs from values. The resulting
54
+ * IO will always return the provided value when run.
55
+ *
56
+ * @template A - The type of the value
57
+ * @param {A} value - The value to wrap in an IO
58
+ * @returns {IO<A>} An IO that returns the value
59
+ *
60
+ * @category Constructors
61
+ * @example
62
+ * ```typescript
63
+ * const io = IO.of(42);
64
+ * IO.run(io); // => 42
65
+ *
66
+ * // Useful for starting chains
67
+ * const result = IO.run(
68
+ * IO.chain((n: number) => IO.of(n * 2))(
69
+ * IO.of(21)
70
+ * )
71
+ * ); // => 42
72
+ * ```
73
+ *
74
+ * @since 2025-09-18
75
+ */
76
+ of: function (value) {
77
+ return function () {
78
+ return value;
79
+ };
80
+ },
81
+ /**
82
+ * Transforms the value inside an IO using the given function.
83
+ * @description Applies a pure function to the value produced by an IO,
84
+ * creating a new IO with the transformed value. This is the functor
85
+ * map operation for IO types.
86
+ *
87
+ * @template A - The input type
88
+ * @template B - The output type
89
+ * @param {function(A): B} f - Function to transform the value
90
+ * @returns {function(IO<A>): IO<B>} A function that transforms IOs
91
+ *
92
+ * @category Transformations
93
+ * @example
94
+ * ```typescript
95
+ * const double = IO.map((n: number) => n * 2);
96
+ * const io = IO.of(21);
97
+ * const doubled = double(io);
98
+ * IO.run(doubled); // => 42
99
+ *
100
+ * // With side effects
101
+ * const random = () => Math.random();
102
+ * const percent = IO.map((n: number) => Math.round(n * 100))(random);
103
+ * IO.run(percent); // => random number 0-100
104
+ * ```
105
+ *
106
+ * @since 2025-09-18
107
+ */
108
+ map: function (f) {
109
+ return function (io) {
110
+ return function () {
111
+ return f(io());
112
+ };
113
+ };
114
+ },
115
+ /**
116
+ * Chains IO-returning operations.
117
+ * @description Sequences two IOs where the second depends on the result
118
+ * of the first. This is the monadic bind operation for IO types.
119
+ *
120
+ * @template A - The input type
121
+ * @template B - The output type
122
+ * @param {function(A): IO<B>} f - Function that returns a new IO
123
+ * @returns {function(IO<A>): IO<B>} A function that chains IOs
124
+ *
125
+ * @category Combinators
126
+ * @example
127
+ * ```typescript
128
+ * const readLine: IO<string> = () => prompt('Enter text:') || '';
129
+ * const toUpper = (s: string): IO<string> => IO.of(s.toUpperCase());
130
+ *
131
+ * const program = IO.chain(toUpper)(readLine);
132
+ * IO.run(program); // prompts user, returns uppercase input
133
+ * ```
134
+ *
135
+ * @since 2025-09-18
136
+ */
137
+ chain: function (f) {
138
+ return function (io) {
139
+ return function () {
140
+ return f(io())();
141
+ };
142
+ };
143
+ },
144
+ /**
145
+ * Alias for chain to match fp-ts naming.
146
+ * @description See {@link chain} for details.
147
+ *
148
+ * @category Combinators
149
+ * @since 2025-09-18
150
+ */
151
+ flatMap: function (f) {
152
+ return function (io) {
153
+ return function () {
154
+ return f(io())();
155
+ };
156
+ };
157
+ },
158
+ /**
159
+ * Applies an IO of a function to an IO of a value.
160
+ * @description Enables applying functions wrapped in IOs to values wrapped
161
+ * in IOs. This is the applicative apply operation for IO types.
162
+ *
163
+ * @template A - The input type
164
+ * @template B - The output type
165
+ * @param {IO<A>} ioValue - IO containing a value
166
+ * @returns {function(IO<function(A): B>): IO<B>} A function that applies IO functions
167
+ *
168
+ * @category Combinators
169
+ * @example
170
+ * ```typescript
171
+ * const add = (a: number) => (b: number) => a + b;
172
+ * const ioAdd = IO.of(add);
173
+ * const io5 = IO.of(5);
174
+ * const io3 = IO.of(3);
175
+ *
176
+ * const result = IO.run(
177
+ * IO.ap(io3)(
178
+ * IO.ap(io5)(
179
+ * IO.map(add)(IO.of(10))
180
+ * )
181
+ * )
182
+ * ); // => 18
183
+ * ```
184
+ *
185
+ * @since 2025-09-18
186
+ */
187
+ ap: function (ioValue) {
188
+ return function (ioFn) {
189
+ return function () {
190
+ return ioFn()(ioValue());
191
+ };
192
+ };
193
+ },
194
+ /**
195
+ * Runs an IO to completion and returns its value.
196
+ * @description Executes an IO, triggering the computation and returning
197
+ * the result. This is where side effects actually occur.
198
+ *
199
+ * @template A - The type of the value
200
+ * @param {IO<A>} io - The IO to run
201
+ * @returns {A} The result of running the IO
202
+ *
203
+ * @category Execution
204
+ * @example
205
+ * ```typescript
206
+ * const io = IO.of(42);
207
+ * const result = IO.run(io); // => 42
208
+ *
209
+ * const sideEffect = () => {
210
+ * console.log('Side effect!');
211
+ * return 'done';
212
+ * };
213
+ * IO.run(sideEffect); // logs "Side effect!", returns 'done'
214
+ * ```
215
+ *
216
+ * @since 2025-09-18
217
+ */
218
+ run: function (io) { return io(); },
219
+ /**
220
+ * Converts an array of IOs into an IO of an array.
221
+ * @description Sequences multiple IOs, running them in order and collecting
222
+ * their results.
223
+ *
224
+ * @template A - The type of values in the IOs
225
+ * @param {IO<A>[]} ios - Array of IOs to sequence
226
+ * @returns {IO<A[]>} An IO containing an array of results
227
+ *
228
+ * @category Combinators
229
+ * @example
230
+ * ```typescript
231
+ * const ios = [
232
+ * IO.of(1),
233
+ * IO.of(2),
234
+ * IO.of(3)
235
+ * ];
236
+ * const combined = IO.sequence(ios);
237
+ * IO.run(combined); // => [1, 2, 3]
238
+ * ```
239
+ *
240
+ * @since 2025-09-18
241
+ */
242
+ sequence: function (ios) {
243
+ return function () {
244
+ return ios.map(function (io) { return io(); });
245
+ };
246
+ },
247
+ /**
248
+ * Maps a function returning an IO over an array and sequences the results.
249
+ * @description Applies an IO-returning function to each element of an array
250
+ * and runs all resulting IOs in sequence.
251
+ *
252
+ * @template A - The input type
253
+ * @template B - The output type
254
+ * @param {function(A): IO<B>} f - Function that returns an IO
255
+ * @returns {function(A[]): IO<B[]>} A function that traverses arrays with IOs
256
+ *
257
+ * @category Combinators
258
+ * @example
259
+ * ```typescript
260
+ * const log = (msg: string): IO<string> => () => {
261
+ * console.log(msg);
262
+ * return msg;
263
+ * };
264
+ *
265
+ * const logAll = IO.traverse(log);
266
+ * const messages = IO.run(
267
+ * logAll(['Hello', 'World'])
268
+ * ); // logs each message, returns ['Hello', 'World']
269
+ * ```
270
+ *
271
+ * @since 2025-09-18
272
+ */
273
+ traverse: function (f) {
274
+ return function (as) {
275
+ return IO.sequence(as.map(f));
276
+ };
277
+ },
278
+ /**
279
+ * Combines the results of a tuple of IOs into an IO of a tuple.
280
+ * @description Takes multiple IOs and returns an IO containing a tuple
281
+ * of their results.
282
+ *
283
+ * @template T - Tuple type of IOs
284
+ * @param {...T} ios - IOs to combine
285
+ * @returns {IO<{ [K in keyof T]: T[K] extends IO<infer U> ? U : never }>} IO of tuple
286
+ *
287
+ * @category Combinators
288
+ * @example
289
+ * ```typescript
290
+ * const io1 = IO.of(1);
291
+ * const io2 = IO.of('hello');
292
+ * const io3 = IO.of(true);
293
+ *
294
+ * const combined = IO.sequenceT(io1, io2, io3);
295
+ * IO.run(combined); // => [1, 'hello', true]
296
+ * ```
297
+ *
298
+ * @since 2025-09-18
299
+ */
300
+ sequenceT: function () {
301
+ var ios = [];
302
+ for (var _i = 0; _i < arguments.length; _i++) {
303
+ ios[_i] = arguments[_i];
304
+ }
305
+ return function () {
306
+ return ios.map(function (io) { return io(); });
307
+ };
308
+ },
309
+ /**
310
+ * Combines the results of a record of IOs into an IO of a record.
311
+ * @description Takes an object with IO values and returns an IO containing
312
+ * an object with the results.
313
+ *
314
+ * @template R - Record type with IO values
315
+ * @param {R} ios - Record of IOs to combine
316
+ * @returns {IO<{ [K in keyof R]: R[K] extends IO<infer U> ? U : never }>} IO of record
317
+ *
318
+ * @category Combinators
319
+ * @example
320
+ * ```typescript
321
+ * const ios = {
322
+ * user: IO.of({ name: 'Alice' }),
323
+ * count: IO.of(42),
324
+ * enabled: IO.of(true)
325
+ * };
326
+ *
327
+ * const combined = IO.sequenceS(ios);
328
+ * IO.run(combined);
329
+ * // => { user: { name: 'Alice' }, count: 42, enabled: true }
330
+ * ```
331
+ *
332
+ * @since 2025-09-18
333
+ */
334
+ sequenceS: function (ios) {
335
+ return function () {
336
+ var entries = Object.entries(ios);
337
+ var result = entries.reduce(function (acc, _a) {
338
+ var _b;
339
+ var key = _a[0], io = _a[1];
340
+ return (__assign(__assign({}, acc), (_b = {}, _b[key] = io(), _b)));
341
+ }, {});
342
+ return result;
343
+ };
344
+ },
345
+ /**
346
+ * Executes an IO for its side effects, discarding the result.
347
+ * @description Runs an IO but returns the original value, useful for IOs
348
+ * that perform side effects where the result isn't needed.
349
+ *
350
+ * @template A - The type of the value
351
+ * @param {function(A): IO<unknown>} f - Function that returns an IO (result discarded)
352
+ * @returns {function(IO<A>): IO<A>} A function that executes side effects
353
+ *
354
+ * @category Combinators
355
+ * @example
356
+ * ```typescript
357
+ * const log = (msg: string): IO<void> => () => console.log(msg);
358
+ *
359
+ * const io = IO.chainFirst((n: number) => log(`Got: ${n}`))(
360
+ * IO.of(42)
361
+ * );
362
+ * IO.run(io); // logs "Got: 42", returns 42
363
+ * ```
364
+ *
365
+ * @since 2025-09-18
366
+ */
367
+ chainFirst: function (f) {
368
+ return function (io) {
369
+ return function () {
370
+ var a = io();
371
+ f(a)();
372
+ return a;
373
+ };
374
+ };
375
+ },
376
+ };
377
+ //# sourceMappingURL=io.mjs.map