Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 = 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?

like image 470
ron Avatar asked Dec 28 '22 22:12

ron


1 Answers

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>
like image 63
oxbow_lakes Avatar answered Apr 27 '23 18:04

oxbow_lakes