列表函数中的通用类型推断

Generic type inference in function from lists

我正在处理一些通用列表实用函数,当主变量是列表时,通用函数的类型推断似乎存在问题。这是用以下代码演示的:

List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
  final list = <T>[];
  for (int i = 0; i < a.length && i < b.length; i++) {
    list.add(combiner(a[i], b[i]));
  }
  return list;
}

void main() {
  final a = [5, 8];
  final b = [7, -3];
  final c = combine(a, b, (a, b) => a + b); // Error

  print(c); 
  // Expected: [12, 5]
}

当我按原样使用此代码时,lambda 中的类型推断将 ab 设置为 Object?,这导致以下错误消息:

The operator '+' can't be unconditionally invoked because the receiver can be 'null'. Try adding a null check to the target ('!').

按照错误消息所说的操作将消息更改为以下内容:

The operator '+' isn't defined for the type 'Object'. Try defining the operator '+'.

问题显然是类型推断将参数分配给 Object? 而不是预期的 int。这可以通过键入参数或显式将泛型类型传递给函数来解决:

final c = combine(a, b, (int a, int b) => a + b);
// OR
final c = combine<int>(a, b, (a, b) => a + b);

但是,这是一个额外的冗长级别,我不想强​​迫这些实用功能的用户必须这样做(更不用说当我必须向他们解释时这将是一个支持问题去做这个)。有没有办法更改函数签名以使其类型推断按预期工作?

这基本上是 ,但在您的情况下,您可以通过使函数成为扩展方法来回避问题,这样 T 是从接收者而不是参数推导出来的:

extension<T> on List<T> {
  List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
    final list = <T>[];
    for (int i = 0; i < length && i < b.length; i++) {
      list.add(combiner(this[i], b[i]));
    }
    return list;
  }
}

void main() {
  final a = [5, 8];
  final b = [7, -3];
  final c = a.combineWith(b, (a, b) => a + b); // Error

  print(c);
  // Expected: [12, 5]
}