从 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?');
});
我目前正在试验 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?');
});