从 dartz 使用 Either 时出现编译器错误

Compiler Error when using Either from dartz

我目前正在试验 flutter 框架和 dart,偶然发现了一个我无法理解的看似奇怪的行为。尽管实际问题发生的上下文要复杂得多,但我什至能够在极其简化的展示中复制它:

Stream<Either<String, int>> result1 = Stream.fromIterable([1, 2, 3, 4, 5])
    .map((number) => number < 4 ? Right(1) : Left('error'))
    .onErrorReturnWith((error) => Left('error'));

虽然上面的示例编译没有矛盾,但我确实得到了下面示例的编译错误:

Error: A value of type 'Left<String, dynamic>' can't be assigned to a variable of type 'Right<dynamic, int>'

Stream<Either<String, int>> result2 = Stream.fromIterable([1, 2, 3, 4, 5])
    .map((number) => Right(1))
    .onErrorReturnWith((error) => Left('error'));

有没有人能够阐明这种方式?

########################################### ###########

另一个例子:

  Future<Either<String, int>> someWebCall() {
Future<int> response = Future.delayed(Duration(milliseconds: 200), () {
  throw SocketException('Well... ...it happens you know...');
});

return response.then((number) {
  return number > 50.0 ? Right(number) : Left('number is too small...');
}).catchError((error) {
  return Left('are you already questioning the meaning of your life?');
});

}

此编译但以运行时错误结束: 类型 'Future' 不是类型 'Future<Either<String, int>>'

的子类型

然后我尝试向编译器提供尽可能多的提示,以提出这种方法:

Future<Either<String, int>> someWebCall() {
Future<int> response = Future.delayed(Duration(milliseconds: 200), () {
  throw SocketException('Well... ...it happens you know...');
});

return response.then<Either<String, int>>((number) {
  return number > 50.0 ? Right(number) : Left('number is too small...') as Either<String, int>;
}).catchError((error) {
  return Left('are you already questioning the meaning of your life?') as Either<String, int>;
});

}

现在我得到: type 'Left<String, dynamic>' 不是 type cast

中 type 'Either<String, int>' 的子类型

我实在想不通

函数 (number) => Right(1) 的类型是 Right<dynamic, int> Function(int),这意味着 map 调用的结果流是 Stream<Right<dynamic, int>>.

onErrorReturnWith 需要 return 与调用它的流的元素类型相同的东西,但它 return 是 Left<String, dynamic>,而不是 Right<dynamic, int>.

最简单的解决方法是告诉 map 调用什么类型 return:

  ...
    .map<Either<String, int>>( .... )

那么类型应该是您所期望的(而不是 Either<dynamic, dynamic> 可能推断出的第一个示例)。

通过深入研究飞镖的类型,我终于明白了是怎么回事。 问题是编译器无法在仅使用 Left 或 Right 的上下文中推断 Either 的类型。 IE。 Left('') 编译器可以将 Either 的左侧部分推断为字符串,而在 Right(5) 中,它能够将 Either 的右侧部分推断为 int。然而,他无法分别弄清楚另一部分。 使用下面的代码按预期工作。

Future<Either<String, int>> someWebCall() {
Future<int> response = Future.delayed(Duration(milliseconds: 200), () {
  throw SocketException('Well... ...it happens you know...');
});

return response.then((number) {
  return number > 50.0 ? Right(number) : Left('number is too small...');
}).catchError((error) {
  return Left<String, int>('are you already questioning the meaning of your life?');
});