在Scala,我可以:
trait Api {
def someApiCall: Either[Failure, GoodResult];
}
或
object SomeObject {
type SomeResult = Either[Failure, GoodResult]
}
trait Api {
def someApiCall: SomeObject.SomeResult;
}
前者对结果类型更明确,因此更容易阅读,但涉及在不同的实现中反复重新输入。这在后者中得到了解决,但是读者不能对第一眼的结果做出很多结论。
如果返回类型为Option
而非Either
,我自然会坚持使用前一版本。对于具有许多类型参数的更复杂类型,第二类更有益。 Either
位于中场。
我的直觉是,从长远来看,后者更易于维护。你怎么看?对此有实践吗?
答案 0 :(得分:10)
做一个
Either[X, Y]
。MaybeResult[Y]
(适用于type MaybeResult[A] = Either[Failure, A]
)坦率地说,即便如此,我也会明确地宣布它。 #2(超出您的建议)的优势在于,使用标准Failure
类型(可能是Exception
或List[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>