【问题标题】:Compiler Error when using Either from dartz使用 dartz 中的 Either 时出现编译器错误
【发布时间】:2021-01-12 18:13:43
【问题描述】:

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

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, 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>' 类型的子类型

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

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' 不是类型转换中的 'Either' 类型的子类型

我实在想不通

【问题讨论】:

    标签: dart either dart-stream dartz


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 非常感谢您的宝贵时间。我添加了另一个例子。你能详细说明一下吗。我确信,Either 必须与 Left 和 Right 兼容,否则我认为这没有任何意义。我做错了什么?
    • 你上面的解释是正确的。当您编写Left("a") 时,编译器将其推断为Left&lt;String, dynamic&gt;("a"),因为它不知道其他类型应该是什么。当您执行test ? Left("string") : Right(42) 时,它将采用Left&lt;String,dynamic&gt;Right&lt;dynamic, int&gt; 的最小上限,即Either&lt;dynamic, dynamic&gt;。为避免此问题,请始终在至少一处(如有必要,可能更多)处写下您想要的 Either 的实际类型。就个人而言,我会将Left 类更改为class Left&lt;T&gt; implements Either&lt;T, Never&gt;,而不是现在的。
    【解决方案2】:

    通过深入研究 dartz 的类型,我终于弄清楚了发生了什么。 问题是编译器无法在只使用 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?');
    });
    

    【讨论】:

      猜你喜欢
      • 2021-11-05
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 2020-09-19
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多