使用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'));

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

错误:无法将类型'Left '的值分配给 类型'Right '

的变量
Stream<Either<String,int>> result2 = Stream.fromIterable([1,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 >'

的子类型

然后,我尝试为编译器提供尽可能多的提示

Future<Either<String,() {
  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>;
});

}

现在我得到: 类型'Left '不是类型转换中类型'Either '的子类型

我真的无法解决这个问题

解决方法

函数(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>那样)。

,

我最终通过深入研究dartz的类型来弄清楚发生了什么。 问题在于,在仅使用Left或Right的上下文中,编译器无法推断Either的类型。即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?');
});