@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/array-utils.d.mts.map +1 -1
- package/dist/array-utils.mjs +6 -3
- package/dist/array-utils.mjs.map +1 -1
- package/dist/composition.d.mts +40 -6
- package/dist/composition.d.mts.map +1 -1
- package/dist/composition.mjs +98 -22
- package/dist/composition.mjs.map +1 -1
- package/dist/index.d.mts +10 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +10 -5
- package/dist/index.mjs.map +1 -1
- package/dist/io.d.mts +326 -0
- package/dist/io.d.mts.map +1 -0
- package/dist/io.mjs +377 -0
- package/dist/io.mjs.map +1 -0
- package/dist/option.d.mts +182 -55
- package/dist/option.d.mts.map +1 -1
- package/dist/option.mjs +251 -60
- package/dist/option.mjs.map +1 -1
- package/dist/performance.d.mts +1 -1
- package/dist/performance.d.mts.map +1 -1
- package/dist/performance.mjs +16 -11
- package/dist/performance.mjs.map +1 -1
- package/dist/reader.d.mts +431 -0
- package/dist/reader.d.mts.map +1 -0
- package/dist/reader.mjs +444 -0
- package/dist/reader.mjs.map +1 -0
- package/dist/result.d.mts +196 -0
- package/dist/result.d.mts.map +1 -1
- package/dist/result.mjs +275 -0
- package/dist/result.mjs.map +1 -1
- package/dist/task.d.mts +361 -0
- package/dist/task.d.mts.map +1 -0
- package/dist/task.mjs +373 -0
- package/dist/task.mjs.map +1 -0
- package/dist/validation.d.mts.map +1 -1
- package/dist/validation.mjs +10 -4
- package/dist/validation.mjs.map +1 -1
- package/package.json +1 -1
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
|