在TypeScript中实现Fantasy-Land规范的Functor遇到问题,请求指导
修正TypeScript中Maybe Functor的实现
嘿,我来帮你把这个Maybe Functor的实现给捋顺,先从你现有代码里的问题说起,再一步步调整到符合Fantasy-Land规范的版本:
1. 先解决Nothing类的核心问题
你现在的Nothing类没必要接收构造函数参数,也不需要存储x——毕竟它代表的就是「空」的状态。另外,Nothing的map方法不管传入什么函数,都应该直接返回空实例(这里用单例模式更高效,避免重复创建对象)。
2. 完善Maybe联合类型
Maybe<T>应该是Just<T>(持有值的情况)和Nothing(空值情况)的联合类型,注意Nothing不需要泛型参数,因为它不持有任何值。
3. 对齐Fantasy-Land的Functor规范
Functor必须满足两个核心定律:
- 恒等律:
fa.map(x => x)必须和fa等价 - 组合律:
fa.map(f).map(g)必须和fa.map(x => g(f(x)))等价
完整修正后的代码
// Nothing类:代表空值状态,用单例模式避免重复创建 class Nothing { private constructor() {} // 复用唯一实例 private static instance: Nothing = new Nothing(); // 对外提供获取实例的静态方法 static get(): Nothing { return this.instance; } // Functor的map方法:空值状态下直接返回自身 map<R>(_: (a: never) => R): Nothing { return Nothing.get(); } } class Just<T> { private readonly x: T; constructor(x: T) { this.x = x; } // Functor的map方法:将函数应用到内部值,返回新的Just实例 map<R>(f: (a: T) => R): Just<R> { return new Just(f(this.x)); } } // 定义Maybe联合类型:要么是带值的Just<T>,要么是空的Nothing type Maybe<T> = Just<T> | Nothing; // 可选辅助函数:快速从可能为null/undefined的值创建Maybe实例 const maybe = <T>(value: T | null | undefined): Maybe<T> => { return value == null ? Nothing.get() : new Just(value); };
验证Functor定律
咱们来测试一下这两个定律是否成立:
恒等律验证
const justFive = new Just(5); console.log(justFive.map(x => x) instanceof Just); // true,内部值仍为5 console.log(Nothing.get().map(x => x) === Nothing.get()); // true,复用了单例
组合律验证
const double = (x: number) => x * 2; const addThree = (x: number) => x + 3; const justTen = new Just(10); const result1 = justTen.map(double).map(addThree); const result2 = justTen.map(x => addThree(double(x))); console.log((result1 as Just<number>).map(x => x) === (result2 as Just<number>).map(x => x)); // true,内部值都是23,符合组合律
额外优化说明
- 给
Nothing用单例模式,减少不必要的对象创建,提升性能 - 给
Just的x加上readonly,确保内部值不可变,贴合函数式编程的不变性原则 - 新增的
maybe辅助函数,能帮你快速把可能为空的值转换成Maybe类型,避免手动判断
内容的提问来源于stack exchange,提问作者Ziggy
相关产品推荐
相关产品推荐

