Dart中如何像Haskell/TypeScript那样单独定义Lambda函数类型并实现
答案
Dart 完全支持类似 Haskell/TypeScript 风格的「先单独定义函数类型蓝图、再基于类型写实现」的写法,不过要注意泛型作用域的写法细节,你之前的测试写法存在类型安全隐患。
你之前测试写法的问题
你写的如下代码:
typedef IdSpecific<T> = T Function(T); IdSpecific id = (x) => x;
这里的泛型参数 T 是绑定在 IdSpecific 这个类型别名本身的,当你没有指定具体类型、直接声明 IdSpecific id 时,Dart 会将 T 推导为 dynamic,所以你传数字、传字符串都能运行,但本质上丢掉了静态类型检查:哪怕你写 IdSpecific id = (x) => x.toString(); 这种不符合「入参返回值同类型」要求的实现,静态检查也不会报错,和你要的多态函数类型效果不一致。
完全对齐 Haskell/TS 风格的正确写法
要实现和 myIdentity :: a -> a、<A>(a: A) => A 完全等价的效果,需要把泛型参数绑定到函数本身,而不是类型别名上,写法如下:
// 1. 单独定义函数类型作为蓝图,泛型参数声明在函数位置 typedef Identity = T Function<T>(T value); // 2. 基于预定义的类型编写实现,静态检查会严格校验实现是否符合类型约束 const Identity identity = (value) => value;
这种写法是完全类型安全的:
- 如果实现不符合类型要求,比如写
const Identity badImpl = (value) => value.toString();,静态检查会直接报错,不会等到运行时才出问题 - 调用时会自动推导泛型类型,和原生泛型函数效果完全一致:
运行结果和你之前测试的一致,但全程有严格的静态类型保障。void main(List<String> arguments) { int numRes = identity(5); // T 自动推导为 int,返回值类型为 int String strRes = identity("Five"); // T 自动推导为 String,返回值类型为 String print('Hello world: $numRes!'); print('Hello world: $strRes!'); }
和你提到的两种常规Dart写法的区别
var identity = (a) => a;:会将函数的入参、返回值都推导为dynamic,没有任何静态类型约束,类型安全性最差A identity<A>(A a) => a;:本身是正确的泛型函数实现,但属于类型和实现耦合的写法,做不到你要的「单独抽离类型蓝图」的拆分需求。
内容的提问来源于stack exchange,提问作者SmoothTraderKen
相关产品推荐
相关产品推荐

