Scala - Define type for Either for compactness or write it explicitly for readability?
In Scala, I can have:
trait Api {
def someApiCall: Either[Failure, GoodResult];
}
or
object SomeObject {
type SomeResult = Eit开发者_运维知识库her[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?
Do one of
- Declare it explicitly as an
Either[X, Y]
. - Declare it as
MaybeResult[Y]
(fortype 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>
精彩评论