Scala - 为紧凑性定义类型还是为了可读性而显式编写它?

发布于 2024-10-29 04:38:29 字数 555 浏览 4 评论 0原文

在 Scala 中,我可以使用:

trait Api {
    def someApiCall: Either[Failure, GoodResult];
}

or ,

object SomeObject {
    type SomeResult = Either[Failure, GoodResult]
}

trait Api {
    def someApiCall: SomeObject.SomeResult;
}

其中前者对结果类型更明确,因此更易于阅读,但涉及在不同的实现中一遍又一遍地重新输入 Either[...] 。这个问题在后者中得到了解决,但是读者乍一看并不能对结果得出太多结论。

如果返回类型是 Option 而不是 Either,我自然会坚持使用以前的版本。对于具有许多类型参数的更复杂的类型,第二种方法会更有利。 Either 位于中场。

我的直觉是,从长远来看,后者更易于维护。你怎么认为?有这方面的实践吗?

In Scala, I can have:

trait Api {
    def someApiCall: Either[Failure, GoodResult];
}

or

object SomeObject {
    type SomeResult = Either[Failure, GoodResult]
}

trait Api {
    def someApiCall: SomeObject.SomeResult;
}

where the former is more explicit about the result type and thus easier to read, but involves retyping Either[...] over and over in different implementations. This is solved in in the latter, but then the reader can't conclude much about the result at first sight.

If the return type were Option instead of Either, I would naturally stick with the former version. For more complex types with many type parameters, the second would be more beneficial. Either is somewhere midfield.

My gut feeling is that on the long run the latter is more maintainable. What do you think? Is there a practice regarding this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

中性美 2024-11-05 04:38:29

执行以下操作之一将

  1. 其显式声明为 Either[X, Y]
  2. 将其声明为 MaybeResult[Y] (对于 type MaybeResult[A] = Either[Failure, A]

坦率地说,即使那样我也会明确声明它。 #2 的优点(相对于您的建议)是,使用标准 Failure 类型(可能是 ExceptionList[String]),您可以不必为您想要使用它的任何地方声明单独的类型别名。

使用Either 的优点是 API 用户100% 清楚正在发生的事情。不过,我会更进一步,使用 Scalaz 的 Validation

def someApiCall : ValidationNEL[String, Result]

这里的优点是 Validation 可以以 Either 所不能的方式组合(否则它们是同构的 /em> 类型)。例如:

def a(i : Int) : ValidationNEL[String, Float]
def b(f : Float) : ValidationNEL[String, Boolean]

那么你可以

a(1) >>= b //ValidationNEL[String, Boolean]

这样写:

scala>  def a(i : Int) : ValidationNEL[String, Float] = error("")
a: (i: Int)scalaz.Scalaz.ValidationNEL[String,Float]

scala> def b(f : Float) : ValidationNEL[String, Boolean] = error("")
b: (f: Float)scalaz.Scalaz.ValidationNEL[String,Boolean]

scala> lazy val c = a(1) >>= b
c: scalaz.Validation[scalaz.NonEmptyList[String],Boolean] = <lazy>

Do one of

  1. Declare it explicitly as an Either[X, Y].
  2. Declare it as MaybeResult[Y] (for type MaybeResult[A] = Either[Failure, A])

Frankly, even then I would declare it explicitly. The advantage of #2 (over your suggestion) is that, with a standard Failure type (perhaps Exception or List[String]), you do not have to declare separate type aliases for everywhere you want to use this.

The advantage to using Either is that it is 100% clear for an API user what is happening. However, I would go one step further and use Scalaz's Validation:

def someApiCall : ValidationNEL[String, Result]

The advantage here is that Validation is composable in ways that Either is not (otherwise they are isomorphic types). For example:

def a(i : Int) : ValidationNEL[String, Float]
def b(f : Float) : ValidationNEL[String, Boolean]

Then you can compose:

a(1) >>= b //ValidationNEL[String, Boolean]

Like so:

scala>  def a(i : Int) : ValidationNEL[String, Float] = error("")
a: (i: Int)scalaz.Scalaz.ValidationNEL[String,Float]

scala> def b(f : Float) : ValidationNEL[String, Boolean] = error("")
b: (f: Float)scalaz.Scalaz.ValidationNEL[String,Boolean]

scala> lazy val c = a(1) >>= b
c: scalaz.Validation[scalaz.NonEmptyList[String],Boolean] = <lazy>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文