functype 0.8.85 → 0.9.1

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 (51) hide show
  1. package/README.md +108 -27
  2. package/dist/{Either-BlY4VB1r.d.ts → Either-BHep7I0d.d.ts} +5 -53
  3. package/dist/Serializable-BbKuhDDL.d.ts +78 -0
  4. package/dist/branded/index.d.ts +8 -7
  5. package/dist/branded/index.mjs +1 -1
  6. package/dist/chunk-BQJB6CCW.mjs +3 -0
  7. package/dist/chunk-BQJB6CCW.mjs.map +1 -0
  8. package/dist/chunk-GHBOC52G.mjs +43 -0
  9. package/dist/chunk-GHBOC52G.mjs.map +1 -0
  10. package/dist/chunk-R2TQJN3P.mjs +2 -0
  11. package/dist/chunk-R2TQJN3P.mjs.map +1 -0
  12. package/dist/either/index.d.ts +2 -2
  13. package/dist/either/index.mjs +1 -1
  14. package/dist/fpromise/index.d.ts +2 -2
  15. package/dist/fpromise/index.mjs +1 -1
  16. package/dist/index.d.ts +554 -147
  17. package/dist/index.mjs +1 -1
  18. package/dist/list/index.d.ts +2 -2
  19. package/dist/list/index.mjs +1 -1
  20. package/dist/map/index.d.ts +3 -3
  21. package/dist/map/index.mjs +1 -1
  22. package/dist/option/index.d.ts +2 -2
  23. package/dist/option/index.mjs +1 -1
  24. package/dist/set/index.d.ts +2 -2
  25. package/dist/set/index.mjs +1 -1
  26. package/dist/try/index.d.ts +2 -2
  27. package/dist/try/index.mjs +1 -1
  28. package/dist/tuple/index.d.ts +75 -2
  29. package/dist/tuple/index.mjs +1 -1
  30. package/package.json +13 -13
  31. package/readme/BUNDLE_OPTIMIZATION.md +74 -0
  32. package/readme/FPromise-Assessment.md +43 -0
  33. package/readme/HKT.md +110 -0
  34. package/readme/ROADMAP.md +113 -0
  35. package/readme/TASK-TODO.md +33 -0
  36. package/readme/TUPLE-EXAMPLES.md +76 -0
  37. package/readme/TaskMigration.md +129 -0
  38. package/readme/ai-guide.md +406 -0
  39. package/readme/examples.md +2093 -0
  40. package/readme/quick-reference.md +514 -0
  41. package/readme/task-error-handling.md +283 -0
  42. package/readme/tasks.md +203 -0
  43. package/readme/type-index.md +238 -0
  44. package/dist/Tuple-ZYh96cGE.d.ts +0 -41
  45. package/dist/Typeable-BBXrKPTY.d.ts +0 -14
  46. package/dist/chunk-B6FR572T.mjs +0 -2
  47. package/dist/chunk-B6FR572T.mjs.map +0 -1
  48. package/dist/chunk-JAPOUVPL.mjs +0 -42
  49. package/dist/chunk-JAPOUVPL.mjs.map +0 -1
  50. package/dist/chunk-TQJDL6YW.mjs +0 -2
  51. package/dist/chunk-TQJDL6YW.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export{F as Base,A as BoundedNumber,B as BoundedString,a as Companion,D as Cond,_ as ESMap,p as Either,w as EmailAddress,J as FPromise,I as FPromiseCompanion,U as FoldableUtils,W as HKT,z as ISO8601Date,X as Identity,t as IntegerNumber,Y as Lazy,Z as LazyList,i as Left,g as List,$ as Map,E as Match,aa as MatchableUtils,G as NAME,v as NonEmptyString,s as NonNegativeNumber,c as None,e as Option,d as OptionConstructor,T as ParseError,C as PatternString,u as PositiveInteger,r as PositiveNumber,h as Right,f as Set,b as Some,ba as Stack,O as Task,L as TaskException,M as TaskResult,H as Throwable,V as Try,n as TypeCheckLeft,m as TypeCheckRight,y as UUID,x as UrlString,q as ValidatedBrand,N as createCancellationTokenSource,S as createErrorSerializer,R as formatError,Q as formatStackTrace,k as isLeft,j as isRight,K as isTaggedThrowable,P as safeStringify,l as tryCatch,o as tryCatchAsync}from'./chunk-JAPOUVPL.mjs';export{d as Tuple,a as Typeable,c as Valuable,b as isTypeable}from'./chunk-B6FR572T.mjs';export{a as Brand,g as BrandedBoolean,f as BrandedNumber,e as BrandedString,d as createBrander,c as hasBrand,b as unbrand}from'./chunk-TQJDL6YW.mjs';//# sourceMappingURL=index.mjs.map
1
+ export{E as Base,z as BoundedNumber,A as BoundedString,C as Cond,aa as ESMap,o as Either,v as EmailAddress,I as FPromise,H as FPromiseCompanion,X as FoldableUtils,Z as HKT,y as ISO8601Date,_ as Identity,s as IntegerNumber,$ as Lazy,U as LazyList,h as Left,f as List,ba as Map,D as Match,ca as MatchableUtils,F as NAME,u as NonEmptyString,r as NonNegativeNumber,b as None,d as Option,c as OptionConstructor,S as ParseError,B as PatternString,t as PositiveInteger,q as PositiveNumber,da as Ref,g as Right,e as Set,a as Some,fa as Stack,N as Task,K as TaskException,L as TaskResult,G as Throwable,Y as Try,m as TypeCheckLeft,l as TypeCheckRight,T as TypedError,x as UUID,w as UrlString,p as ValidatedBrand,V as Validation,ea as Valuable,M as createCancellationTokenSource,R as createErrorSerializer,Q as formatError,P as formatStackTrace,W as isExtractable,j as isLeft,i as isRight,J as isTaggedThrowable,O as safeStringify,k as tryCatch,n as tryCatchAsync}from'./chunk-GHBOC52G.mjs';export{a as Companion,b as Tuple}from'./chunk-BQJB6CCW.mjs';export{a as Brand,g as BrandedBoolean,f as BrandedNumber,e as BrandedString,d as createBrander,c as hasBrand,b as unbrand}from'./chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,2 +1,2 @@
1
- export { L as List } from '../Either-BlY4VB1r.js';
2
- import '../Typeable-BBXrKPTY.js';
1
+ export { L as List } from '../Either-BHep7I0d.js';
2
+ import '../Serializable-BbKuhDDL.js';
@@ -1,2 +1,2 @@
1
- export{g as List}from'../chunk-JAPOUVPL.mjs';import'../chunk-B6FR572T.mjs';import'../chunk-TQJDL6YW.mjs';//# sourceMappingURL=index.mjs.map
1
+ export{f as List}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,6 +1,6 @@
1
- import { T as Traversable, C as Collection, S as Serializable, P as Pipe, F as Foldable, O as Option } from '../Either-BlY4VB1r.js';
2
- import { a as Typeable, T as Type } from '../Typeable-BBXrKPTY.js';
3
- import { T as Tuple } from '../Tuple-ZYh96cGE.js';
1
+ import { T as Traversable, C as Collection, O as Option } from '../Either-BHep7I0d.js';
2
+ import { a as Typeable, S as Serializable, P as Pipe, F as Foldable, T as Type } from '../Serializable-BbKuhDDL.js';
3
+ import { Tuple } from '../tuple/index.js';
4
4
 
5
5
  /**
6
6
  * A traversable interface for map that excludes map and flatMap operations
@@ -1,2 +1,2 @@
1
- export{$ as Map}from'../chunk-JAPOUVPL.mjs';import'../chunk-B6FR572T.mjs';import'../chunk-TQJDL6YW.mjs';//# sourceMappingURL=index.mjs.map
1
+ export{ba as Map}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,2 +1,2 @@
1
- export { N as None, O as Option, n as OptionConstructor, m as Some } from '../Either-BlY4VB1r.js';
2
- import '../Typeable-BBXrKPTY.js';
1
+ export { N as None, O as Option, m as OptionConstructor, S as Some } from '../Either-BHep7I0d.js';
2
+ import '../Serializable-BbKuhDDL.js';
@@ -1,2 +1,2 @@
1
- export{c as None,e as Option,d as OptionConstructor,b as Some}from'../chunk-JAPOUVPL.mjs';import'../chunk-B6FR572T.mjs';import'../chunk-TQJDL6YW.mjs';//# sourceMappingURL=index.mjs.map
1
+ export{b as None,d as Option,c as OptionConstructor,a as Some}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,2 +1,2 @@
1
- export { p as Set } from '../Either-BlY4VB1r.js';
2
- import '../Typeable-BBXrKPTY.js';
1
+ export { n as Set } from '../Either-BHep7I0d.js';
2
+ import '../Serializable-BbKuhDDL.js';
@@ -1,2 +1,2 @@
1
- export{f as Set}from'../chunk-JAPOUVPL.mjs';import'../chunk-B6FR572T.mjs';import'../chunk-TQJDL6YW.mjs';//# sourceMappingURL=index.mjs.map
1
+ export{e as Set}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,5 +1,5 @@
1
- import { a as FunctypeBase, b as Extractable, P as Pipe, E as Either } from '../Either-BlY4VB1r.js';
2
- import { T as Type } from '../Typeable-BBXrKPTY.js';
1
+ import { F as FunctypeBase, a as Extractable, E as Either } from '../Either-BHep7I0d.js';
2
+ import { P as Pipe, T as Type } from '../Serializable-BbKuhDDL.js';
3
3
 
4
4
  /**
5
5
  * Possible types of Try instances
@@ -1,2 +1,2 @@
1
- export{V as Try}from'../chunk-JAPOUVPL.mjs';import'../chunk-B6FR572T.mjs';import'../chunk-TQJDL6YW.mjs';//# sourceMappingURL=index.mjs.map
1
+ export{Y as Try}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,2 +1,75 @@
1
- import '../Typeable-BBXrKPTY.js';
2
- export { T as Tuple } from '../Tuple-ZYh96cGE.js';
1
+ import { T as Type, F as Foldable, P as Pipe, S as Serializable, a as Typeable } from '../Serializable-BbKuhDDL.js';
2
+
3
+ interface Tuple<T extends Type[]> extends Foldable<T[number]>, Pipe<Tuple<T>>, Serializable<Tuple<T>>, Typeable<"Tuple"> {
4
+ get<K extends number>(index: K): T[K];
5
+ map<U extends Type[]>(f: (value: T) => U): Tuple<U>;
6
+ flatMap<U extends Type[]>(f: (value: T) => Tuple<U>): Tuple<U>;
7
+ toArray(): T;
8
+ length: number;
9
+ [Symbol.iterator](): Iterator<T[number]>;
10
+ toString(): string;
11
+ toValue(): {
12
+ _tag: "Tuple";
13
+ value: T;
14
+ };
15
+ }
16
+ /**
17
+ * Tuple provides a type-safe, fixed-length array with functional operations.
18
+ *
19
+ * @example
20
+ * // Creating tuples
21
+ * const t1 = Tuple([1, "hello", true])
22
+ * const t2 = Tuple.of(1, "hello", true)
23
+ * const pair = Tuple.pair("key", 42)
24
+ *
25
+ * @example
26
+ * // Type-safe access
27
+ * const triple = Tuple.triple("x", 10, true)
28
+ * const first = triple.get(0) // string
29
+ * const second = triple.get(1) // number
30
+ * const third = triple.get(2) // boolean
31
+ *
32
+ * @example
33
+ * // Functional operations
34
+ * const doubled = Tuple([1, 2, 3])
35
+ * .map(arr => arr.map(x => x * 2))
36
+ * .toArray() // [2, 4, 6]
37
+ */
38
+ declare const Tuple: (<T extends Type[]>(values: T) => Tuple<T>) & {
39
+ /**
40
+ * Create a Tuple from multiple arguments
41
+ * @example
42
+ * const t = Tuple.of(1, "hello", true)
43
+ * // TypeScript infers: Tuple<[number, string, boolean]>
44
+ */
45
+ of: <T extends Type[]>(...values: T) => Tuple<T>;
46
+ /**
47
+ * Create a Tuple of size 2 (pair)
48
+ * @example
49
+ * const pair = Tuple.pair("key", 42)
50
+ * // TypeScript infers: Tuple<[string, number]>
51
+ */
52
+ pair: <A extends Type, B extends Type>(first: A, second: B) => Tuple<[A, B]>;
53
+ /**
54
+ * Create a Tuple of size 3 (triple)
55
+ * @example
56
+ * const triple = Tuple.triple("x", 10, true)
57
+ * // TypeScript infers: Tuple<[string, number, boolean]>
58
+ */
59
+ triple: <A extends Type, B extends Type, C extends Type>(first: A, second: B, third: C) => Tuple<[A, B, C]>;
60
+ /**
61
+ * Create an empty Tuple
62
+ * @example
63
+ * const empty = Tuple.empty()
64
+ * // TypeScript infers: Tuple<[]>
65
+ */
66
+ empty: () => Tuple<[]>;
67
+ /**
68
+ * Create a Tuple from an array (alias for constructor)
69
+ * @example
70
+ * const t = Tuple.from([1, 2, 3])
71
+ */
72
+ from: <T extends Type[]>(values: T) => Tuple<T>;
73
+ };
74
+
75
+ export { Tuple };
@@ -1,2 +1,2 @@
1
- export{d as Tuple}from'../chunk-B6FR572T.mjs';//# sourceMappingURL=index.mjs.map
1
+ export{b as Tuple}from'../chunk-BQJB6CCW.mjs';//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functype",
3
- "version": "0.8.85",
3
+ "version": "0.9.1",
4
4
  "type": "module",
5
5
  "description": "A smallish functional library for TypeScript",
6
6
  "author": "jordan.burke@gmail.com",
@@ -14,26 +14,26 @@
14
14
  "devDependencies": {
15
15
  "@eslint/compat": "^1.3.1",
16
16
  "@eslint/eslintrc": "^3.3.1",
17
- "@eslint/js": "^9.29.0",
18
- "@types/node": "^22.15.33",
19
- "@typescript-eslint/eslint-plugin": "^8.35.0",
20
- "@typescript-eslint/parser": "^8.35.0",
17
+ "@eslint/js": "^9.32.0",
18
+ "@types/node": "^22.16.5",
19
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
20
+ "@typescript-eslint/parser": "^8.38.0",
21
21
  "@vitest/coverage-v8": "^3.2.4",
22
22
  "@vitest/ui": "^3.2.4",
23
- "cross-env": "^7.0.3",
24
- "eslint": "^9.29.0",
25
- "eslint-config-prettier": "^10.1.5",
23
+ "cross-env": "^10.0.0",
24
+ "eslint": "^9.32.0",
25
+ "eslint-config-prettier": "^10.1.8",
26
26
  "eslint-plugin-functional": "^9.0.2",
27
27
  "eslint-plugin-import": "^2.32.0",
28
- "eslint-plugin-prettier": "^5.5.1",
28
+ "eslint-plugin-prettier": "^5.5.3",
29
29
  "eslint-plugin-simple-import-sort": "^12.1.1",
30
- "fast-check": "^4.1.1",
31
- "globals": "^16.2.0",
32
- "prettier": "^3.6.1",
30
+ "fast-check": "^4.2.0",
31
+ "globals": "^16.3.0",
32
+ "prettier": "^3.6.2",
33
33
  "rimraf": "^6.0.1",
34
34
  "ts-node": "^10.9.2",
35
35
  "tsup": "^8.5.0",
36
- "typedoc": "^0.28.5",
36
+ "typedoc": "^0.28.8",
37
37
  "typescript": "5.8.3",
38
38
  "vitest": "^3.2.4"
39
39
  },
@@ -0,0 +1,74 @@
1
+ # Bundle Size Optimization Guide
2
+
3
+ ## Overview
4
+
5
+ Functype is designed with tree-shaking in mind, allowing you to optimize your application's bundle size by only including the specific modules you need.
6
+
7
+ ## Import Strategies
8
+
9
+ ### Strategy 1: Selective Module Imports (Recommended)
10
+
11
+ Import only the specific modules you need to reduce bundle size significantly.
12
+
13
+ ```typescript
14
+ import { Option } from "functype/option"
15
+ import { Either } from "functype/either"
16
+
17
+ // Usage
18
+ const option = Option.some(42)
19
+ const either = Either.right("value")
20
+ ```
21
+
22
+ ### Strategy 2: Direct Constructor Imports (Smallest Bundle)
23
+
24
+ For the most aggressive tree-shaking, import only the specific constructors and functions you need.
25
+
26
+ ```typescript
27
+ import { some, none } from "functype/option"
28
+ import { right } from "functype/either"
29
+
30
+ // Usage
31
+ const option = some(42)
32
+ const none_value = none()
33
+ const either = right("value")
34
+ ```
35
+
36
+ ## Bundle Size Comparison
37
+
38
+ | Import Strategy | Approximate Bundle Size | Best For |
39
+ | --------------- | ------------------------ | -------------------------- |
40
+ | Selective | 200-500 bytes per module | Most applications |
41
+ | Direct | <200 bytes per feature | Size-critical applications |
42
+
43
+ ## Common Module Sizes
44
+
45
+ | Module | Approximate Size (minified) | Gzipped Size |
46
+ | -------- | --------------------------- | ------------ |
47
+ | Option | ~200 bytes | ~140 bytes |
48
+ | Either | ~290 bytes | ~190 bytes |
49
+ | List | ~170 bytes | ~125 bytes |
50
+ | Try | ~170 bytes | ~125 bytes |
51
+ | Tuple | ~120 bytes | ~100 bytes |
52
+ | FPromise | ~200 bytes | ~140 bytes |
53
+
54
+ ## Additional Tips
55
+
56
+ 1. **Import Analysis**: Use tools like [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) or [rollup-plugin-visualizer](https://github.com/btd/rollup-plugin-visualizer) to analyze your bundle and identify opportunities for optimization.
57
+
58
+ 2. **Dynamic Imports**: Consider using dynamic imports for rarely used functionality:
59
+
60
+ ```typescript
61
+ // Only load when needed
62
+ const useRareFeature = async () => {
63
+ const { someLargeUtility } = await import("functype/some-large-module")
64
+ return someLargeUtility()
65
+ }
66
+ ```
67
+
68
+ 3. **Development vs Production**: During development, you might prefer the convenience of importing everything. In production builds, switch to selective imports.
69
+
70
+ 4. **Peer Dependencies**: Functype has minimal dependencies, and the only external dependency (`safe-stable-stringify`) is quite small.
71
+
72
+ ## Need Help?
73
+
74
+ If you need assistance with optimizing your bundle size further, please open an issue on our GitHub repository.
@@ -0,0 +1,43 @@
1
+ # FPromise Implementation Assessment
2
+
3
+ ## Overview
4
+
5
+ This document provides an assessment of whether the FPromise implementation is ready to replace the old main branch version, with particular focus on potential impacts to implementing libraries outside this one.
6
+
7
+ ## Strengths of the FPromise Implementation
8
+
9
+ 1. **Comprehensive Error Handling**: FPromise provides rich error handling capabilities including `mapError`, `tapError`, `recover`, `recoverWith`, `recoverWithF`, `filterError`, and `logError`.
10
+
11
+ 2. **Either Integration**: FPromise has built-in conversion to/from Either with `toEither()` and `fromEither()`, which aligns well with the functional programming approach used in the Task implementation.
12
+
13
+ 3. **Promise Compatibility**: FPromise implements the PromiseLike interface, ensuring compatibility with async/await and standard Promise chains.
14
+
15
+ 4. **Extensive Test Coverage**: The test suite is comprehensive, covering basic functionality, error handling, recovery mechanisms, and real-world scenarios.
16
+
17
+ 5. **Retry Mechanisms**: The implementation includes multiple retry strategies (basic retry, retry with backoff, and retry with options).
18
+
19
+ ## Potential Compatibility Issues
20
+
21
+ 1. **Import Path Differences**: The Task.ts file imports from `"'core/throwable/Throwable"'` and `"'either/Either"'` with unusual quotes, while the actual imports should use `@/` prefix. This might cause issues if external libraries rely on these specific import paths.
22
+
23
+ 2. **Type Compatibility**: The Task implementation uses `Either<Throwable, T>` for error handling, while FPromise uses a more generic approach. Libraries expecting specific Either structures might need adjustments.
24
+
25
+ 3. **API Surface Changes**: External libraries that directly interact with the Promise implementation might need to adapt to the new methods and patterns provided by FPromise.
26
+
27
+ ## Recommendation
28
+
29
+ The FPromise implementation is technically sound and provides significant improvements, but to avoid breaking implementing libraries outside this one:
30
+
31
+ 1. **Gradual Migration**: Consider a phased approach where both implementations coexist temporarily.
32
+
33
+ 2. **Version Bumping**: This change warrants a major version bump to signal potential breaking changes.
34
+
35
+ 3. **Documentation**: Provide clear migration guides for dependent libraries.
36
+
37
+ 4. **Import Path Fixes**: Ensure import paths are consistent and follow the project's conventions.
38
+
39
+ 5. **Compatibility Layer**: Consider providing a thin compatibility layer for libraries that can't immediately migrate to the new API.
40
+
41
+ ## Conclusion
42
+
43
+ The FPromise implementation appears ready to replace the old main branch version from a technical perspective, but careful migration planning is necessary to minimize disruption to implementing libraries.
package/readme/HKT.md ADDED
@@ -0,0 +1,110 @@
1
+ # Higher-Kinded Types (HKT)
2
+
3
+ Higher-kinded types allow for writing generic code that works across different container types like `Option`, `List`, `Either`, and `Try`. This is a powerful abstraction that lets you create algorithms that work with any type that supports certain operations, without having to rewrite them for each specific type.
4
+
5
+ ## Introduction
6
+
7
+ In functional programming, many operations like `map`, `flatMap`, or `sequence` follow similar patterns across different data structures. The HKT module provides a unified way to work with these operations for any supporting container type.
8
+
9
+ ## Key Concepts
10
+
11
+ 1. **Kind**: A type-level function representing a higher-kinded type relationship
12
+ 2. **Container Types**: Data structures that contain values (Option, List, Either, etc.)
13
+ 3. **Type Constructor**: A function that takes a type and returns a new type
14
+
15
+ ## Basic Operations
16
+
17
+ ### Map
18
+
19
+ Apply a function to a value inside a container:
20
+
21
+ ```typescript
22
+ import { Option, HKT } from "functype"
23
+
24
+ const option = Option(42)
25
+ const doubled = HKT.map(option, (x) => x * 2) // Option(84)
26
+ ```
27
+
28
+ ### FlatMap
29
+
30
+ Apply a function that returns a container to a value inside a container, then flatten the result:
31
+
32
+ ```typescript
33
+ const option = Option(42)
34
+ const result = HKT.flatMap(option, (x) => Option(x * 2)) // Option(84)
35
+ ```
36
+
37
+ ### Flatten
38
+
39
+ Flatten a nested container:
40
+
41
+ ```typescript
42
+ const nestedOption = Option(Option(42))
43
+ const flattened = HKT.flatten(nestedOption) // Option(42)
44
+ ```
45
+
46
+ ## Advanced Operations
47
+
48
+ ### Sequence
49
+
50
+ Transform a container of containers into a container of container (e.g., `Option<List<A>>` to `List<Option<A>>`):
51
+
52
+ ```typescript
53
+ const optionOfList = Option(List([1, 2, 3]))
54
+ const listOfOptions = HKT.sequence(optionOfList)
55
+ // List([Option(1), Option(2), Option(3)])
56
+ ```
57
+
58
+ ### Traverse
59
+
60
+ Transform each element in a container using a function that returns another container type, then sequence the results:
61
+
62
+ ```typescript
63
+ const list = List([1, 2, 3])
64
+ const result = HKT.traverse(list, (x) => Option(x * 2))
65
+ // Option(List([2, 4, 6]))
66
+ ```
67
+
68
+ ### Applicative (ap)
69
+
70
+ Apply a function inside a container to a value inside another container:
71
+
72
+ ```typescript
73
+ const optionFn = Option((x: number) => x * 2)
74
+ const optionValue = Option(21)
75
+ const result = HKT.ap(optionFn, optionValue) // Option(42)
76
+ ```
77
+
78
+ ## Supported Container Types
79
+
80
+ The HKT module currently supports the following container types:
81
+
82
+ - `Option<A>`
83
+ - `List<A>`
84
+ - `Either<E, A>`
85
+ - `Try<A>`
86
+
87
+ ## Creating Generic Algorithms
88
+
89
+ The power of HKT is in creating algorithms that work with any container type:
90
+
91
+ ```typescript
92
+ // A function that works with any container implementing map
93
+ function increment<F extends (a: number) => any>(container: Kind<F, number>): Kind<F, number> {
94
+ return HKT.map(container, (x) => x + 1)
95
+ }
96
+
97
+ // Works with any container
98
+ increment(Option(41)) // Option(42)
99
+ increment(List([1, 2, 3])) // List([2, 3, 4])
100
+ increment(Right<string, number>(41)) // Right(42)
101
+ ```
102
+
103
+ ## Implementing Your Own Container Types
104
+
105
+ To make your custom container types work with HKT, you need to:
106
+
107
+ 1. Implement the appropriate methods (`map`, `flatMap`, etc.)
108
+ 2. Add type checking in the HKT functions
109
+
110
+ This allows seamless integration with the rest of the functional programming ecosystem.
@@ -0,0 +1,113 @@
1
+ # Functype Roadmap (2025-2026)
2
+
3
+ This roadmap outlines the planned development path for the Functype library, focusing on expanding functionality, improving performance, ensuring API consistency, and enhancing TypeScript integration.
4
+
5
+ ## Q2 2025: Core Functional Data Types
6
+
7
+ ### Lazy Evaluation
8
+
9
+ - [ ] Implement `LazyList` / `Stream` for efficient processing of potentially infinite sequences
10
+ - [ ] Add common operations: `map`, `filter`, `take`, `drop`, etc.
11
+ - [ ] Implement memoization for evaluated values
12
+
13
+ ### Validation Type
14
+
15
+ - [ ] Create `Validation` data type for applicative validation
16
+ - [ ] Support collecting multiple errors (unlike Either which short-circuits)
17
+ - [ ] Add utilities for combining validation results
18
+
19
+ ### Performance Foundation
20
+
21
+ - [ ] Add memoization utilities for expensive function calls
22
+ - [ ] Implement a basic benchmarking suite for measuring performance
23
+ - [ ] Standardize performance metrics across data structures
24
+
25
+ ## Q3 2025: Advanced Functional Patterns & Optimizations
26
+
27
+ ### Type Classes
28
+
29
+ - [x] Implement `Foldable` typeclass with fold, foldLeft, and foldRight methods
30
+ - [x] Implement `Matchable` typeclass for pattern matching
31
+ - [ ] Implement proper `Functor` and `Monad` typeclasses
32
+ - [ ] Add `Applicative` typeclass
33
+ - [ ] Support `Traversable` with comprehensive HKT
34
+
35
+ ### Monad Implementations
36
+
37
+ - [ ] Implement `Reader` monad for dependency injection
38
+ - [ ] Add `State` monad for managing state transformations
39
+ - [ ] Create `IO` monad for pure handling of side effects
40
+ - [ ] Add comprehensive documentation and examples
41
+
42
+ ### Performance Improvements
43
+
44
+ - [ ] Implement structural sharing for immutable collections
45
+ - [ ] Optimize recursive operations for large data structures
46
+ - [ ] Add performance comparison against other FP libraries
47
+
48
+ ### Lenses & Optics
49
+
50
+ - [ ] Implement lens abstraction for immutable updates
51
+ - [ ] Add prism implementation for optional data
52
+ - [ ] Create utilities for composing lenses and prisms
53
+
54
+ ## Q4 2025: TypeScript Enhancements & API Consistency
55
+
56
+ ### TypeScript Integration
57
+
58
+ - [x] Add support for higher-kinded types
59
+ - [ ] Remove `any` from HKT
60
+ - [x] Implement branded/nominal types for stronger type safety
61
+ - [ ] Add type-level utilities using newer TypeScript features
62
+ - [ ] Leverage const type parameters and tuple manipulation
63
+
64
+ ### API Normalization
65
+
66
+ - [ ] Review and standardize API across all modules
67
+ - [ ] Ensure consistent implementation of the Scala-inspired pattern
68
+ - [ ] Standardize import patterns (@imports throughout)
69
+ - [ ] Create migration guides for API changes
70
+
71
+ ## Q1 2026: Testing, Documentation & Community Support
72
+
73
+ ### Testing Expansion
74
+
75
+ - [ ] Add test coverage metrics and set coverage goals
76
+ - [ ] Expand property-based testing across all modules
77
+ - [ ] Create interoperability tests with popular libraries
78
+ - [ ] Add more specialized test cases for error handling
79
+
80
+ ### Documentation & Examples
81
+
82
+ - [ ] Add comprehensive documentation for all modules
83
+ - [ ] Create step-by-step migration guides from imperative to functional
84
+ - [ ] Add real-world examples showcasing practical applications
85
+ - [ ] Create tutorial sections for beginners
86
+
87
+ ### Community Engagement
88
+
89
+ - [ ] Create contribution guidelines and templates
90
+ - [ ] Set up automated issue/PR handling
91
+ - [ ] Establish regular release schedule
92
+ - [ ] Add community forum/discussion platform
93
+
94
+ ## Ongoing Priorities
95
+
96
+ ### Compatibility
97
+
98
+ - [ ] Ensure compatibility with Node.js LTS versions
99
+ - [ ] Maintain browser compatibility
100
+ - [ ] Support for Deno and other runtimes
101
+ - [ ] Test with various bundlers (webpack, esbuild, etc.)
102
+
103
+ ### Bundle Size
104
+
105
+ - [x] Optimize tree-shaking
106
+ - [x] Provide guidance on importing only needed modules
107
+ - [x] Add bundle size monitoring to CI/CD
108
+
109
+ ### Community Feedback
110
+
111
+ - [ ] Regular review of GitHub issues and feature requests
112
+ - [ ] Prioritization based on community needs
113
+ - [ ] Transparent development process
@@ -0,0 +1,33 @@
1
+ # Task TODO
2
+
3
+ ## Goals
4
+
5
+ - Enhance the Task module as an adapter between promise-based code and functional patterns
6
+ - Improve interoperability with existing JavaScript/TypeScript codebases
7
+ - Allow gradual migration to functional patterns without complete rewrites
8
+
9
+ ## Implementation Tasks
10
+
11
+ - [x] Review current Task implementation for completeness of promise integration
12
+ - [x] Ensure robust error handling in sync/async conversions
13
+ - [x] Document explicit try/catch/finally semantics
14
+ - [x] Add examples showing migration from promise-based to functional patterns
15
+ - [x] Add utilities to simplify Task composition with promise-returning functions
16
+ - [x] Create migration guide for converting promise chains to Task operations
17
+
18
+ ## Design Considerations
19
+
20
+ - Maintain clear separation between synchronous and promise-based operations
21
+ - Preserve functional error handling patterns while supporting promise interop
22
+ - Keep API consistent with the rest of the library's functional approach
23
+
24
+ ## Completed Enhancements
25
+
26
+ - Added `fromPromise` adapter to convert promise-returning functions to Task-compatible functions
27
+ - Added `toPromise` converter to transform Task results back to promises
28
+ - Enhanced documentation with clearer descriptions of functionality
29
+ - Created TaskMigration.md guide showing how to migrate from promises to functional Task patterns
30
+ - Added comprehensive tests for the new adapter methods
31
+ - Improved error handler behavior to ensure handlers are always called, even for TaggedThrowable errors
32
+ - Enhanced error chaining to preserve context while supporting logging in error handlers
33
+ - Added test coverage to verify error handlers are always called for all error types
@@ -0,0 +1,76 @@
1
+ # Tuple Enhanced with Modern TypeScript Features
2
+
3
+ ## What's Improved
4
+
5
+ Our enhanced `Tuple` implementation leverages modern TypeScript features:
6
+
7
+ 1. **Const type parameters** (TypeScript 5.0+)
8
+ 2. **Variadic tuple types** (TypeScript 4.0+)
9
+ 3. **Stronger type inference** for tuple elements
10
+
11
+ ## Examples
12
+
13
+ ### Basic Usage
14
+
15
+ ```typescript
16
+ import { Tuple } from "@/tuple"
17
+
18
+ // Create a tuple with mixed types
19
+ const personTuple = Tuple(["John Doe", 42, true])
20
+
21
+ // Access values with type safety
22
+ const name = personTuple.get(0) // Type is string
23
+ const age = personTuple.get(1) // Type is number
24
+ const active = personTuple.get(2) // Type is boolean
25
+
26
+ // Transform the tuple
27
+ const mapped = personTuple.map((values) => values.map((x) => (typeof x === "number" ? x * 2 : x)))
28
+ ```
29
+
30
+ ### Preserving Literal Types
31
+
32
+ ```typescript
33
+ // Using 'as const' with the enhanced implementation
34
+ const literalTuple = Tuple([1, "hello", true] as const)
35
+
36
+ // TypeScript now knows the exact types:
37
+ const first = literalTuple.get(0) // Type is exactly 1 (not just number)
38
+ const second = literalTuple.get(1) // Type is exactly 'hello' (not just string)
39
+ const third = literalTuple.get(2) // Type is exactly true (not just boolean)
40
+
41
+ // Benefits:
42
+ // - Better type checking
43
+ // - Autocomplete shows exact values
44
+ // - Prevents invalid index access
45
+ ```
46
+
47
+ ### Type-Level Utilities (for future improvements)
48
+
49
+ ```typescript
50
+ // Example of potential future type utilities
51
+ type FirstElement<T extends Tuple<unknown[]>> = T extends Tuple<[infer F, ...unknown[]]> ? F : never
52
+
53
+ // Extract first element's type
54
+ type First = FirstElement<typeof literalTuple> // Would be 1
55
+
56
+ // Could expand to other utilities like:
57
+ // - LastElement
58
+ // - RemoveFirst
59
+ // - Prepend<T, Item>
60
+ // - etc.
61
+ ```
62
+
63
+ ## When Is This Useful?
64
+
65
+ 1. **Strong typing for heterogeneous collections**:
66
+ - When you need to store different types in a fixed structure
67
+ - When you want type safety beyond what arrays provide
68
+
69
+ 2. **APIs returning fixed-length, mixed-type results**:
70
+ - When a function returns multiple values of different types
71
+
72
+ 3. **Data transformation pipelines**:
73
+ - When you need to transform data while preserving type information
74
+
75
+ 4. **Configuration objects with fixed format**:
76
+ - When config must follow a specific format with specific types at each position