Scala - 为紧凑性定义Either的类型,还是为了可读性而明确写入?

时间:2011-04-01 09:50:38

标签: scala api-design either

在Scala,我可以:

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

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

trait Api {
    def someApiCall: SomeObject.SomeResult;
}

前者对结果类型更明确,因此更容易阅读,但涉及在不同的实现中反复重新输入。这在后者中得到了解决,但是读者不能对第一眼的结果做出很多结论。

如果返回类型为Option而非Either,我自然会坚持使用前一版本。对于具有许多类型参数的更复杂类型,第二类更有益。 Either位于中场。

我的直觉是,从长远来看,后者更易于维护。你怎么看?对此有实践吗?

1 个答案:

答案 0 :(得分:10)

做一个

  1. 明确声明为Either[X, Y]
  2. 将其声明为MaybeResult[Y](适用于type MaybeResult[A] = Either[Failure, A]
  3. 坦率地说,即便如此,我也会明确地宣布它。 #2(超出您的建议)的优势在于,使用标准Failure类型(可能是ExceptionList[String]),您必须声明在您想要使用它的任何地方使用单独的类型别名。

    使用Either的好处是API用户 100%清除正在发生的事情。但是,我会更进一步使用Scalaz的Validation

    def someApiCall : ValidationNEL[String, Result]
    

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

    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>