Валидация Scala - Либо с правым уклоном

Наконец-то в Scala 2.12 появился параметр Either с правым смещением. Я слышал, что это можно использовать для проверки, но я не могу себе этого представить. Я не могу найти хороший пример.
Может кто-нибудь объяснить мне, как эта монада может помочь мне с проверкой? Также какие еще варианты использования могут быть охвачены этим улучшенным Either?


person PawelN    schedule 06.12.2016    source источник
comment
Что заставляет вас думать, что Either является правым?   -  person jwvh    schedule 07.12.2016
comment
официальные примечания к выпуску Scala - scala-lang.org/news/2.12.0   -  person PawelN    schedule 07.12.2016
comment
Ознакомьтесь с документацией по Either на веб-сайте Cats.   -  person Peter Neyens    schedule 07.12.2016


Ответы (1)


Either[A, B], будь то предвзятость или нет, отлично подходит для проверки / обработки исключений. Если сделать его правильно смещенным, нам будет легче составлять над ним операции.

Допустим, мы хотим проверить объект, какие формы может принимать метод проверки? Простейшей формой был бы предикат, метод, принимающий произвольный объект и возвращающий Bool:

sealed trait Base
case class Foo(I: Int)
case class Bar(s: String)

def isValid(b: Base): Bool = b match {
  case Foo(i) => i > 18
  case Bar(s) => s.length > 5
}

Это сработает, но иногда может быть недостаточно. Что, если это API, обращенный к пользователю, и мы хотим четко указать возможные ошибки с полученным объектом, чтобы пользователь быстро понял, что пошло не так?

Что, если вместо возврата Bool мы либо вернем список ошибок, либо вернем сам действительный объект? Это позволит нам в дальнейшем составлять:

def validate(b: Base): Either[List[String], Base] = b match {
  case Foo(i) => if (i > 18) Right(b) else Left(List("i must be greater than 18"))
  case Bar(s) => if (s.length > 5) Right(b) else Left(List("s must be longer than 5 chars"))
}

Теперь мы можем нанести на него карту:

val foo = Foo(42)
val result = validate(foo).map { case Foo(i) => s"yay, valid foo number: $i" } 
result match {
  case Left(errors) => println(s"Something went wrong: ${errors.mkString(", ")}")
  case Right(msg) => println(msg)
}

Мы получаем две вещи. Во-первых, это возможность составлять валидацию с другими операциями и откладывать обработку ошибок, а во-вторых, это явные ошибки. Мы могли бы даже пойти дальше и сделать эти ошибки типизированными, чтобы пользователь мог сопоставить их и применить обработку ошибок для каждого варианта использования, но это в другой раз.

person Yuval Itzchakov    schedule 06.12.2016
comment
Теперь он у меня есть. Я думал о чем-то более сложном, но ошибался. Это просто, и я делаю то, что хочу. Я попытался перестроить свое решение. Спасибо. - person PawelN; 07.12.2016