0

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

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

虽然上面的示例编译不矛盾,但我确实收到以下示例的编译错误:

错误:“Left<String, dynamic>”类型的值不能分配给“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?');
});

}

这会编译但以运行时错误结束:类型“未来”不是类型“未来<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>' is not a subtype of type 'Either<String, int>' in type cast

我真的无法理解这个

4

2 回答 2

0

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

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

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

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

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

于 2020-09-26T19:51:10.753 回答
0

通过深入研究 dartz 的类型,我终于弄清楚了发生了什么。问题是编译器无法在仅使用 Left 或 Right 的上下文中推断出 Either 的类型。即Left('') 编译器可以将Either 的Left 部分推断为字符串,而在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?');
});
于 2020-09-27T06:47:09.750 回答