Scala - Определите тип для Either для компактности или напишите его явно для удобства чтения? - PullRequest
4 голосов
/ 01 апреля 2011

В 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 Ответ

10 голосов
/ 01 апреля 2011

Выполните одно из

  1. Объявите его явно как Either[X, Y].
  2. Объявите его как MaybeResult[Y] (для type MaybeResult[A] = Either[Failure, A])

Честно говоря, даже тогда я бы объявил об этом явно.Преимущество # 2 (по сравнению с вашим предложением) состоит в том, что со стандартным типом Failure (возможно, Exception или List[String]) вы не должны объявлять отдельные псевдонимы типов для всех, где вы хотите

Преимущество использования Either состоит в том, что 100% ясно для пользователя API, что происходит.Тем не менее, я бы сделал еще один шаг и использовал бы Scalaz Validation:

def someApiCall : ValidationNEL[String, Result]

Преимущество здесь в том, что Validation компонуется так, как Either нет (иначе они изоморфны типы).Например:

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>
...