Имея дело с Опцией и Любым типом - идиоматические преобразования? - PullRequest
10 голосов
/ 22 сентября 2011

Я, вероятно, упускаю что-то, что правильно в документации, но я не могу в этом много смысла - я учил себя Scala в основном методом проб и ошибок.

Учитывая функцию f: A => C, каков идиоматический способ выполнить следующие преобразования?

Either[A, B] -> Either[C, B]

Either[B, A] -> Either[B, C]

(Если у меня есть два такихфункции и хотите конвертировать обе стороны, могу ли я сделать все это сразу или я должен применить идиому дважды последовательно?)

Option[A] -> Option[C]

(У меня есть ощущение, что это должноиспользуйте как-нибудь for (...) yield; я, вероятно, просто не обращаю на это внимания и буду чувствовать себя глупо, когда увижу ответ)

А что именно точно является "проекцией" EitherВ любом случае?

Ответы [ 3 ]

18 голосов
/ 22 сентября 2011

Вы можете либо:

either.left.map(f)

, либо:

either.right.map(f)

Вы также можете использовать для понимания: for (x <- either.left) yield f(x)

Вот ещеконкретный пример выполнения map для Either[Boolean, Int]:

scala> val either: Either[Boolean, Int] = Right(5)
either: Either[Boolean, Int] = Right(5)

scala> val e2 = either.right.map(_ > 0)
either: Either[Boolean, Boolean] = Right(true)

scala> e2.left.map(!_)
either: Either[Boolean, Boolean] = Right(true)

РЕДАКТИРОВАТЬ:

Как это работает?Скажем, у вас есть Either[A, B].При вызове left или right создается объект LeftProjection или RightProjection, который является оболочкой, содержащей объект Either[A, B].

Для оболочки left, последующий mapфункция f: A => C применяется для преобразования Either[A, B] в Either[C, B].Это делается с помощью сопоставления с образцом под капотом, чтобы проверить, действительно ли Either является Left.Если это так, он создает новый Left[C, B].Если нет, он просто изменяется, создает новый Right[C, B] с тем же базовым значением.

И наоборот для оболочки right.Фактически, сказать either.right.map(f) означает - если объект any (Either[A, B]) содержит значение Right, отобразите его.В противном случае, оставьте все как есть, но измените тип B любого объекта, как если бы вы его отобразили.

Так что технически эти проекции - просто обертки.Семантически это способ сказать, что вы делаете что-то, что предполагает, что значение, хранимое в объекте Either, равно Left или Right.Если это предположение неверно, отображение ничего не делает, но параметры типа соответственно изменяются.

3 голосов
/ 07 февраля 2012

Учитывая f: A=>B и xOpt: Option[A], xOpt map f производит Option[B], который вам нужен.

Учитывая f: A=>B и xOrY: Either[A, C], xOrY.left.map(f) производит Either, который вы ищетесопоставление только первого компонента;Точно так же вы можете иметь дело с RightProjection из Either.

Если у вас есть две функции, вы можете определить сопоставление для обоих компонентов, xOrY.fold(f, g).

0 голосов
/ 25 апреля 2013
val e1:Either[String, Long] = Right(1)
val e2:Either[Int,Boolean] = e1.left.map(_.size).right.map( _ >1 )
// e2: Either[Int,Boolean] = Right(false)
...