functype 0.8.67 → 0.8.69
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/README.md +136 -6
- package/dist/Either-BfXNbTHo.d.ts +533 -0
- package/dist/Map-vivbm5n0.d.ts +65 -0
- package/dist/{Tuple-DfdXAbL_.d.ts → Valuable-CtuVEKTZ.d.ts} +17 -10
- package/dist/chunk-5DWCHDSA.mjs +39 -0
- package/dist/chunk-5DWCHDSA.mjs.map +1 -0
- package/dist/chunk-7PQA3W7W.mjs +2 -0
- package/dist/chunk-7PQA3W7W.mjs.map +1 -0
- package/dist/either/index.d.ts +2 -3
- package/dist/either/index.mjs +1 -1
- package/dist/fpromise/index.d.ts +373 -3
- package/dist/fpromise/index.mjs +1 -1
- package/dist/index.d.ts +533 -2
- package/dist/index.mjs +1 -1
- package/dist/list/index.d.ts +2 -3
- package/dist/list/index.mjs +1 -1
- package/dist/map/index.d.ts +4 -3
- package/dist/map/index.mjs +1 -1
- package/dist/option/index.d.ts +2 -987
- package/dist/option/index.mjs +1 -1
- package/dist/set/index.d.ts +2 -3
- package/dist/set/index.mjs +1 -1
- package/dist/try/index.d.ts +59 -3
- package/dist/try/index.mjs +1 -1
- package/dist/tuple/index.d.ts +12 -1
- package/dist/tuple/index.mjs +1 -1
- package/package.json +17 -16
- package/readme/BUNDLE_OPTIMIZATION.md +74 -0
- package/readme/FPromise-Assessment.md +43 -0
- package/readme/HKT.md +110 -0
- package/readme/ROADMAP.md +113 -0
- package/readme/TASK-IMPLEMENTATION.md +290 -0
- package/readme/TASK-TODO.md +40 -0
- package/readme/TASK-UPDATES.md +64 -0
- package/readme/TUPLE-EXAMPLES.md +79 -0
- package/readme/TaskMigration.md +129 -0
- package/readme/ai-guide.md +406 -0
- package/readme/examples.md +2093 -0
- package/readme/quick-reference.md +514 -0
- package/readme/task-cancellation-progress.md +258 -0
- package/readme/task-error-handling.md +128 -0
- package/readme/task-quick-reference.md +157 -0
- package/readme/tasks.md +205 -0
- package/readme/type-index.md +238 -0
- package/dist/chunk-NTL4HYMA.mjs +0 -18
- package/dist/chunk-NTL4HYMA.mjs.map +0 -1
- package/dist/chunk-PXFJPCM7.mjs +0 -2
- package/dist/chunk-PXFJPCM7.mjs.map +0 -1
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
# AI Guide to Functype
|
|
2
|
+
|
|
3
|
+
This document provides a concise reference for AI models to understand the patterns and usage of the Functype library.
|
|
4
|
+
|
|
5
|
+
## Core Types
|
|
6
|
+
|
|
7
|
+
### Option<T>
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// Create: Option(value) returns Some(value) or None
|
|
11
|
+
const some = Option(42) // Some(42)
|
|
12
|
+
const none = Option(null) // None
|
|
13
|
+
|
|
14
|
+
// Access: .get() or .getOrElse(default)
|
|
15
|
+
some.get() // 42
|
|
16
|
+
none.getOrElse("default") // "default"
|
|
17
|
+
|
|
18
|
+
// Transform: .map(), .flatMap(), .filter()
|
|
19
|
+
some.map((x) => x * 2) // Some(84)
|
|
20
|
+
some.flatMap((x) => Option(x.toString())) // Some("42")
|
|
21
|
+
some.filter((x) => x > 50) // None
|
|
22
|
+
|
|
23
|
+
// Pattern match: .fold() or .match()
|
|
24
|
+
some.fold(
|
|
25
|
+
() => "empty",
|
|
26
|
+
(val) => `value: ${val}`,
|
|
27
|
+
) // "value: 42"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Either<L, R>
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// Create: Right(value) or Left(error)
|
|
34
|
+
const right = Right<string, number>(42)
|
|
35
|
+
const left = Left<string, number>("error")
|
|
36
|
+
|
|
37
|
+
// From functions: Either.tryCatch()
|
|
38
|
+
const result = Either.tryCatch(
|
|
39
|
+
() => JSON.parse('{"key":"value"}'),
|
|
40
|
+
(err) => `Parse error: ${err}`,
|
|
41
|
+
) // Right({key: "value"})
|
|
42
|
+
|
|
43
|
+
// Transform: .map(), .mapLeft(), .flatMap()
|
|
44
|
+
right.map((x) => x * 2) // Right(84)
|
|
45
|
+
left.mapLeft((e) => e.toUpperCase()) // Left("ERROR")
|
|
46
|
+
right.flatMap((x) => Right(x.toString())) // Right("42")
|
|
47
|
+
|
|
48
|
+
// Pattern match: .fold() or .match()
|
|
49
|
+
right.fold(
|
|
50
|
+
(err) => `Error: ${err}`,
|
|
51
|
+
(val) => `Success: ${val}`,
|
|
52
|
+
) // "Success: 42"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Try<T>
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// Create: Try(() => potentially_throwing_function())
|
|
59
|
+
const success = Try(() => 42)
|
|
60
|
+
const failure = Try(() => {
|
|
61
|
+
throw new Error("Failed")
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// Transform: .map(), .flatMap(), .recover()
|
|
65
|
+
success.map((x) => x * 2) // Success(84)
|
|
66
|
+
failure.recover("default") // Success("default")
|
|
67
|
+
success.flatMap((x) => Try(() => x.toString())) // Success("42")
|
|
68
|
+
|
|
69
|
+
// Pattern match: .fold() or .match()
|
|
70
|
+
success.fold(
|
|
71
|
+
(err) => `Error: ${err.message}`,
|
|
72
|
+
(val) => `Success: ${val}`,
|
|
73
|
+
) // "Success: 42"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### List<T>
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// Create: List([...elements])
|
|
80
|
+
const list = List([1, 2, 3, 4, 5])
|
|
81
|
+
|
|
82
|
+
// Access: .head(), .tail(), .at(index)
|
|
83
|
+
list.head() // Some(1)
|
|
84
|
+
list.tail() // List([2, 3, 4, 5])
|
|
85
|
+
|
|
86
|
+
// Transform: .map(), .flatMap(), .filter()
|
|
87
|
+
list.map((x) => x * 2) // List([2, 4, 6, 8, 10])
|
|
88
|
+
list.filter((x) => x % 2 === 0) // List([2, 4])
|
|
89
|
+
list.flatMap((x) => List([x, x])) // List([1, 1, 2, 2, 3, 3, 4, 4, 5, 5])
|
|
90
|
+
|
|
91
|
+
// Reduce: .foldLeft(), .foldRight()
|
|
92
|
+
list.foldLeft(0)((acc, x) => acc + x) // 15
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Map<K, V>
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// Create: Map({key: value})
|
|
99
|
+
const map = Map({ a: 1, b: 2, c: 3 })
|
|
100
|
+
|
|
101
|
+
// Access: .get(key), .getOrElse(key, default)
|
|
102
|
+
map.get("a") // Some(1)
|
|
103
|
+
map.getOrElse("d", 0) // 0
|
|
104
|
+
|
|
105
|
+
// Transform: .map(), .filter()
|
|
106
|
+
map.map((v) => v * 2) // Map({a: 2, b: 4, c: 6})
|
|
107
|
+
map.filter((v) => v > 1) // Map({b: 2, c: 3})
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Set<T>
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Create: Set([...elements])
|
|
114
|
+
const set = Set([1, 2, 3, 4, 5])
|
|
115
|
+
|
|
116
|
+
// Operations: .add(), .remove(), .has()
|
|
117
|
+
set.add(6) // Set([1, 2, 3, 4, 5, 6])
|
|
118
|
+
set.remove(3) // Set([1, 2, 4, 5])
|
|
119
|
+
set.has(2) // true
|
|
120
|
+
|
|
121
|
+
// Set operations: .union(), .intersect(), .difference()
|
|
122
|
+
const set2 = Set([4, 5, 6, 7])
|
|
123
|
+
set.union(set2) // Set([1, 2, 3, 4, 5, 6, 7])
|
|
124
|
+
set.intersect(set2) // Set([4, 5])
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### FPromise<T, E>
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Create: FPromise.resolve(), FPromise.reject(), FPromise.tryCatch()
|
|
131
|
+
const success = FPromise.resolve(42)
|
|
132
|
+
const failure = FPromise.reject(new Error("Failed"))
|
|
133
|
+
|
|
134
|
+
// From async functions
|
|
135
|
+
const result = FPromise.tryCatchAsync(
|
|
136
|
+
async () => await fetchData(),
|
|
137
|
+
(err) => new Error(`Fetch failed: ${err}`),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
// Transform: .map(), .mapError(), .flatMap()
|
|
141
|
+
success.map((x) => x * 2) // FPromise<84, never>
|
|
142
|
+
failure.mapError((e) => new Error(`Enhanced: ${e.message}`))
|
|
143
|
+
success.flatMap((x) => FPromise.resolve(x.toString()))
|
|
144
|
+
|
|
145
|
+
// Error handling
|
|
146
|
+
failure.recover("default") // FPromise<"default", never>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Task
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Create: Task().Sync() or Task().Async()
|
|
153
|
+
const syncTask = Task().Sync(
|
|
154
|
+
() => 42,
|
|
155
|
+
(err) => new Error(`Failed: ${err}`),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
const asyncTask = Task().Async(
|
|
159
|
+
async () => await fetchData(),
|
|
160
|
+
async (err) => new Error(`Fetch failed: ${err}`),
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
// From promise
|
|
164
|
+
const fetchUser = Task({ name: "UserFetch" }).fromPromise(fetchUserAPI)
|
|
165
|
+
|
|
166
|
+
// Usage
|
|
167
|
+
syncTask.then((value) => console.log(value)).catch((error) => console.error(error))
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Tuple
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Create: Tuple(...values)
|
|
174
|
+
const pair = Tuple(42, "hello")
|
|
175
|
+
|
|
176
|
+
// Access: .first(), .second(), etc.
|
|
177
|
+
pair.first() // 42
|
|
178
|
+
pair.second() // "hello"
|
|
179
|
+
|
|
180
|
+
// Transform: .map(), .mapFirst(), .mapSecond()
|
|
181
|
+
pair.mapFirst((x) => x * 2) // Tuple(84, "hello")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Common Patterns
|
|
185
|
+
|
|
186
|
+
### Type Safety
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Branded types
|
|
190
|
+
type UserId = Brand<string, "UserId">
|
|
191
|
+
const UserId = (id: string): UserId => {
|
|
192
|
+
if (!/^U\d{6}$/.test(id)) throw new Error("Invalid ID format")
|
|
193
|
+
return id as UserId
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Type-safe functions
|
|
197
|
+
function getUserById(id: UserId): User {
|
|
198
|
+
/* ... */
|
|
199
|
+
}
|
|
200
|
+
getUserById(UserId("U123456")) // Works
|
|
201
|
+
getUserById("U123456") // Type error
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Error Handling
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Option for nullable values
|
|
208
|
+
const maybeUser = Option(findUser(id))
|
|
209
|
+
maybeUser.fold(
|
|
210
|
+
() => console.log("User not found"),
|
|
211
|
+
(user) => console.log("User:", user.name),
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
// Either for errors with context
|
|
215
|
+
const validationResult = validateForm(formData)
|
|
216
|
+
validationResult.fold(
|
|
217
|
+
(errors) => handleErrors(errors),
|
|
218
|
+
(data) => processForm(data),
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
// Try for exception safety
|
|
222
|
+
const parseResult = Try(() => JSON.parse(input))
|
|
223
|
+
parseResult.fold(
|
|
224
|
+
(err) => console.error("Parse error:", err.message),
|
|
225
|
+
(data) => console.log("Data:", data),
|
|
226
|
+
)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Chaining Operations
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Option chain
|
|
233
|
+
const userCity = Option(user)
|
|
234
|
+
.flatMap((u) => Option(u.address))
|
|
235
|
+
.flatMap((a) => Option(a.city))
|
|
236
|
+
.getOrElse("Unknown")
|
|
237
|
+
|
|
238
|
+
// Either chain
|
|
239
|
+
parseInput(input)
|
|
240
|
+
.flatMap(validateData)
|
|
241
|
+
.flatMap(transformData)
|
|
242
|
+
.fold(
|
|
243
|
+
(err) => handleError(err),
|
|
244
|
+
(result) => displayResult(result),
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
// List processing
|
|
248
|
+
List([1, 2, 3, 4, 5])
|
|
249
|
+
.filter((n) => n % 2 === 0)
|
|
250
|
+
.map((n) => n * n)
|
|
251
|
+
.foldLeft(0)((acc, n) => acc + n) // 20 (4 + 16)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Pattern Matching
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// Using match method
|
|
258
|
+
result.match({
|
|
259
|
+
Some: (value) => `Found: ${value}`,
|
|
260
|
+
None: () => "Not found",
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
// Using fold method
|
|
264
|
+
either.fold(
|
|
265
|
+
(left) => `Error: ${left}`,
|
|
266
|
+
(right) => `Success: ${right}`,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
// Using MatchableUtils
|
|
270
|
+
const isPositive = MatchableUtils.when(
|
|
271
|
+
(n: number) => n > 0,
|
|
272
|
+
(n) => `Positive: ${n}`,
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
const isNegative = MatchableUtils.when(
|
|
276
|
+
(n: number) => n < 0,
|
|
277
|
+
(n) => `Negative: ${n}`,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
const defaultCase = MatchableUtils.default((n: number) => `Zero: ${n}`)
|
|
281
|
+
|
|
282
|
+
// Usage
|
|
283
|
+
isPositive(42) ?? isNegative(42) ?? defaultCase(42) // "Positive: 42"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Functional Composition
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
// Using pipe for sequential operations
|
|
290
|
+
import { pipe } from "functype"
|
|
291
|
+
|
|
292
|
+
const result = pipe(
|
|
293
|
+
Option(input),
|
|
294
|
+
(opt) => opt.map((s) => s.trim()),
|
|
295
|
+
(opt) => opt.filter((s) => s.length > 0),
|
|
296
|
+
(opt) => opt.map((s) => parseInt(s, 10)),
|
|
297
|
+
(opt) => opt.filter((n) => !isNaN(n)),
|
|
298
|
+
(opt) => opt.getOrElse(0),
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
// Converting between types
|
|
302
|
+
import { FoldableUtils } from "functype"
|
|
303
|
+
|
|
304
|
+
const optionAsList = FoldableUtils.toList(option)
|
|
305
|
+
const listAsOption = FoldableUtils.toOption(list)
|
|
306
|
+
const tryAsEither = FoldableUtils.toEither(tryVal, "Default error")
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Key Principles
|
|
310
|
+
|
|
311
|
+
1. **Immutability**: All data structures return new instances when modified
|
|
312
|
+
2. **Type Safety**: Strong TypeScript typing throughout the library
|
|
313
|
+
3. **Null Safety**: No null/undefined values within containers (Option, Either, etc.)
|
|
314
|
+
4. **Error Handling**: Explicit error handling using functional patterns
|
|
315
|
+
5. **Pattern Matching**: Consistent APIs for inspecting and handling variants
|
|
316
|
+
6. **Composability**: Methods designed for chaining and composition
|
|
317
|
+
7. **Consistency**: Similar patterns across different data structures
|
|
318
|
+
|
|
319
|
+
## Common Imports
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
// Full package import (not recommended for production)
|
|
323
|
+
import { Option, Either, Try, List } from "functype"
|
|
324
|
+
|
|
325
|
+
// Optimized imports for tree-shaking
|
|
326
|
+
import { Option } from "functype/option"
|
|
327
|
+
import { Either } from "functype/either"
|
|
328
|
+
import { List } from "functype/list"
|
|
329
|
+
|
|
330
|
+
// Individual constructor imports
|
|
331
|
+
import { some, none } from "functype/option"
|
|
332
|
+
import { right, left } from "functype/either"
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Type Class Hierarchy
|
|
336
|
+
|
|
337
|
+
- **Functor**: `map` - Transform values while preserving structure
|
|
338
|
+
- **Applicative**: Apply functions inside containers
|
|
339
|
+
- **Monad**: `flatMap` - Chain operations that return containerized values
|
|
340
|
+
- **Foldable**: `fold`, `foldLeft`, `foldRight` - Collapse structure
|
|
341
|
+
- **Traversable**: Convert/sequence containers
|
|
342
|
+
|
|
343
|
+
## Anti-Patterns to Avoid
|
|
344
|
+
|
|
345
|
+
1. ❌ **Unnecessary Unwrapping**:
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
// Bad
|
|
349
|
+
if (option.isDefined()) {
|
|
350
|
+
doSomething(option.get())
|
|
351
|
+
} else {
|
|
352
|
+
doSomethingElse()
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Good
|
|
356
|
+
option.fold(
|
|
357
|
+
() => doSomethingElse(),
|
|
358
|
+
(value) => doSomething(value),
|
|
359
|
+
)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
2. ❌ **Throwing from Inside Containers**:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
// Bad
|
|
366
|
+
option.map((value) => {
|
|
367
|
+
if (!isValid(value)) throw new Error("Invalid")
|
|
368
|
+
return transform(value)
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
// Good
|
|
372
|
+
option.flatMap((value) => (isValid(value) ? Option(transform(value)) : Option(null)))
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
3. ❌ **Not Using Composition**:
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// Bad
|
|
379
|
+
const a = option.map((x) => x + 1)
|
|
380
|
+
const b = a.filter((x) => x > 10)
|
|
381
|
+
const c = b.getOrElse(0)
|
|
382
|
+
|
|
383
|
+
// Good
|
|
384
|
+
const result = option
|
|
385
|
+
.map((x) => x + 1)
|
|
386
|
+
.filter((x) => x > 10)
|
|
387
|
+
.getOrElse(0)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
4. ❌ **Mixing Imperative and Functional Styles**:
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// Bad
|
|
394
|
+
let result = 0
|
|
395
|
+
option.fold(
|
|
396
|
+
() => {
|
|
397
|
+
result = 42
|
|
398
|
+
},
|
|
399
|
+
(value) => {
|
|
400
|
+
result = value
|
|
401
|
+
},
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
// Good
|
|
405
|
+
const result = option.getOrElse(42)
|
|
406
|
+
```
|