Для начала: в данном случае немного странно использовать набор (для набора значений Validated[..., Double]
).Какая часть семантики Set
вас волнует?Неупорядоченность?Уникальность?
В общем, самый простой способ суммировать элементы, имеющие экземпляр Monoid
, - это использовать метод combineAll
для вещей с экземпляром Foldable
, например, List
(ноне Set
).
import cats.data.{ Validated, ValidatedNel }
import cats.instances.double._, cats.instances.list._
import cats.syntax.foldable._
// or just import cats.implicits._
val val1: ValidatedNel[String, Double] = Validated.valid(1.0)
val val2: ValidatedNel[String, Double] = Validated.valid(2.0)
val bad1: ValidatedNel[String, Double] = Validated.invalidNel("foo")
val bad2: ValidatedNel[String, Double] = Validated.invalidNel("bar")
val values = Set(val1, val2)
val withSomeBadOnes = Set(val1, bad1, val2, bad2)
А потом:
scala> values.toList.combineAll
res0: cats.data.ValidatedNel[String,Double] = Valid(3.0)
scala> withSomeBadOnes.toList.combineAll
res1: cats.data.ValidatedNel[String,Double] = Invalid(NonEmptyList(foo, bar))
Я думаю, это то, что вы подразумеваете под "Если некоторые элементы в значениях, то я хотел бы иметьсоответствующие строки "?
Вы также можете использовать SortedSet
, поскольку Cats предоставляет экземпляр Foldable
для SortedSet
, но это не так удобно:
scala> import cats.implicits._
import cats.implicits._
scala> import scala.collection.immutable.SortedSet
import scala.collection.immutable.SortedSet
scala> (SortedSet.empty[ValidatedNel[String, Double]] ++ values).combineAll
res2: cats.data.ValidatedNel[String,Double] = Valid(3.0)
scala> (SortedSet.empty[ValidatedNel[String, Double]] ++ withSomeBadOnes).combineAll
res3: cats.data.ValidatedNel[String,Double] = Invalid(NonEmptyList(bar, foo))
Вы также можете использоватьстандартный fold
и оператор |+|
для моноидов:
scala> values.fold(Validated.valid(0.0))(_ |+| _)
res4: cats.data.ValidatedNel[String,Double] = Valid(3.0)
Подводя итог: вы не можете позвонить combineAll
непосредственно на ваш Set
, поскольку Cats не предоставляет Foldable
для Set
.Я бы посоветовал тщательно пересмотреть использование Set
в любом случае, но если вы решите придерживаться его, у вас есть несколько вариантов: преобразовать в List
или SortedSet
, как у меня выше, используйте стандартный fold
на Set
, или, наконец, напишите свой собственный Foldable[Set]
или используйте тот из alleycats.