【问题标题】:why does cat's effect async signature uses Either[Throwable, A] and not Try[A]?为什么 cat 的效果异步签名使用 Either[Throwable, A] 而不是 Try[A]?
【发布时间】:2019-09-26 03:41:52
【问题描述】:

很久以前,我们团队内部就使用Try[A]Either[Throwable, A] 进行了长期争论,最终我们选择了Try[A],因为当Either 的左侧是Throwable 时,它们在语义上是相同的。那个时候我正在寻找一个使用Either[Throwable, A]的代码库,但我找不到。

但是今天在观看 Fabio Labella 在How do Fibers Work? A Peek Under the Hood 上的演讲时, 下面的签名让我印象深刻


    def async[A](k: (Either[Throwable, A] => Unit) => Unit): F[A]

所以我的问题是,使用Either[Throwable, A] 代替Try[A] 有什么具体原因吗?推荐哪一个?

【问题讨论】:

  • 恰好Try[A]Either[Throwable, A] 同构。我的问题是,有什么理由使用Either[Throwable, A] 还是只是个人选择?
  • 这可能与 Try 不是 Monad(几乎是 monad,但不完全是)这一事实有关。 Cats 是纯函数式编程库,因此他们可能决定使用纯函数式结构。

标签: scala error-handling functional-programming scala-cats


【解决方案1】:

我不确定Try[A]Either[Throwable, A] 之间的语义是否完全同构。比如我们可以改变Either的bias

val e: Either[Throwable, Int] = Left(new Exception("boom"))
for (s <- e.left) yield s.getMessage.length
res5: scala.util.Either[Int,Int] = Left(4)

或者换边

e.swap
res6: scala.util.Either[Int,Throwable] = Right(java.lang.Exception: boom)

考虑一些不寻常的情况,我们认为Throwables 实际上是预期结果,因此希望它们位于Right 端。也许我们正在构建一些纯功能测试库,我们希望在其中提供一个用于断言异常的 API。可以想象将这些语义编码为Either[A, Throwable]

Either 相对于Try 的另一个潜在优势可能是猫为它提供了更多的扩展方法。例如,考虑import cats.syntax.either._ 中的所有好东西,而我不知道Try 有类似的东西。假设我们想将所有错误累积在一个列表中而不是短路,那么我们可以像这样简单地traverse(_.toValidatedNec)

import cats.syntax.either._
import cats.instances.list._
import cats.syntax.traverse._

val l: List[Either[Throwable, Int]] = List(Right(1), Right(2), Left(new RuntimeException("boom")), Right(3), Left(new RuntimeException("crash")))
l.traverse(_.toValidatedNec)
res0: cats.data.ValidatedNec[Throwable,List[Int]] = Invalid(Chain(java.lang.RuntimeException: boom, java.lang.RuntimeException: crash))

要达到与Try相似的效果,我认为我们必须更加努力。

【讨论】:

    【解决方案2】:

    略读this question 的答案,以下是差异列表:

    • 这并不意味着成功和失败,它只是一个 A 或 B 的容器
    • 使用 Try 清楚地识别计算中的潜在故障,该故障由异常表示
    • Try[X] 的优点在于,您可以将更多操作链接到它,如果它真的是 Success,他们将执行,如果是 Failure,他们将不会执行
    • Try 有许多其他有用的方法,当然还有它的配套应用方法,这使得它非常方便地用于其预期用途 - 异常处理。
    • 两者都可以用来指定错误的描述,可以显示给客户端。 Try - 使用堆栈跟踪包装异常
    • 适合 Try 的候选方法是可能引发异常的方法或向外部系统发送请求的方法

    【讨论】:

      猜你喜欢
      • 2019-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-18
      • 2022-12-07
      • 1970-01-01
      • 2011-09-07
      • 1970-01-01
      相关资源
      最近更新 更多