Как превратить "Either [Error, Option [Either [Error, Account]]]" в "Either [Error, Option [Account]]" с кошками уровня типа?

Я использую кошек, интересно, как с их помощью преобразовать данные.

От

val data = Either[Error, Option[Either[Error, Account]]]

to

val target: Either[Error, Option[Account]] = howToConvert(data)

Если что-то Error произойдет, результатом будет Left(error) с первой появившейся ошибкой.

Теперь я могу это сделать с помощью:

data match {
  case Left(e) => Left(e)
  case Right(Some(Right(y))) => Right(Some(y))
  case Right(Some(Left(e))) => Left(e)
  case Right(None) => Right(None)
}

Но я ищу легкий путь


person Freewind    schedule 15.01.2018    source источник
comment
Должен ли Right(None) быть сопоставлен с Right(None)?   -  person thesamet    schedule 15.01.2018
comment
@thesamet Да, спасибо! Я обновлю это   -  person Freewind    schedule 15.01.2018


Ответы (2)


Самый простой способ сделать это - sequence внутренний Option, чтобы получить Either[Error, Either[Error, Option[Account]]], а затем сгладить его. С синтаксисом кошек это действительно просто:

import cats.implicits._

val target: Either[Error, Option[Account]] =
  data.flatMap(_.sequence)

Чтобы уточнить, sequence переворачивает конструктор типа «наизнанку», то есть внутренний Option[Either[Error, Account]] превращается в Either[Error, Option[Account]].

person Luka Jacobowitz    schedule 15.01.2018
comment
Красиво, но что еще нужно импортировать? Я получаю: polymorphic expression cannot be instantiated to expected type; [error] found : [G[_], A]G[Option[A]] [error] required: scala.util.Either[Error,Option[Account]] [error] val my: Either[Error, Option[Account]] = data.flatMap(_.sequence) - person thesamet; 15.01.2018
comment
Это все, что вам нужно. Однако вам может потребоваться включить -Ypartial-unification. - person Luka Jacobowitz; 15.01.2018

Вот «простой» способ, который предполагает только синтаксис с правым смещением (Scala 2.12) или кошачий синтаксис.

val target: Either[Error, Option[Account]] =
    data.flatMap(_.map(_.map(Some(_))).getOrElse(Right(None)))
person thesamet    schedule 15.01.2018