Кошки: сопоставление кортежей с одним и тем же аппликативом

#scala #tuples #scala-cats #applicative #either

#scala #кортежи #scala-cats #аппликативный #либо

Вопрос:

Допустим, у меня есть:

 val x1: Either[String, Int] = Right(1)
val x2: Either[String, Float] = Left("Nope")
val x3: Either[String, Double] = Left("Not Today")
  

Я хочу объединить их вместе и получить Either[NonEmptyList[String], (Int, Float, Double)] . Чтобы сделать это, я в настоящее время делаю следующее:

 import cats.syntax.all._
(
  x1.toValidatedNel,
  x2.toValidatedNel,
  x3.toValidatedNel
).tupled
 .toEither
  

Что делает работу, но немного утомительно. Есть ли способ сделать это, вызвав toValidatedNel только один раз? что-то вроде:

 (x1, x2, x3)
  .fooMap(_.toValidatedNel)
  .tupled
  .toEither
  

fooMap Существует ли такое где-нибудь в cats? или нам это нужно HLists ?

Ответ №1:

Используя Shapeless, это

 import shapeless.syntax.std.tuple._
object toValidatedNel extends Poly1 {
  implicit def cse[A, B, AA >: A]: Case.Aux[Either[A, B], ValidatedNel[AA, B]] = at(_.toValidatedNel[AA])
}

(x1, x2, x3)
  .map(toValidatedNel)
  .tupled
  .toEither