如何对Set [ValidatedNel [String,Double]]求和?

时间:2019-06-13 16:00:41

标签: scala functional-programming scala-cats

我有这个:

Set[ValidatedNel[String, Double]] 

我想对其中的Doubles求和:

ValidatedNel[String, Double]

如果值中的某些元素是,那么我想要匹配的字符串。

我玩了Set.sum和Numeric都没用...

这是我想要实现的目标的测试:

  test("Summing ValidatedNel works") {
    val val1: ValidatedNel[String, Double] = Valid(1.0)
    val val2: ValidatedNel[String, Double] = Valid(2.0)
    val values: Set[ValidatedNel[String, Double]] = Set(val1, val2)

    val validatedNelNumeric: Numeric[ValidatedNel[String, Double]] = ???
    val sum = values.sum(validatedNelNumeric)

    assert(sum == Valid(3.0))
  }

我无法创建validatedNelNumeric ...

1 个答案:

答案 0 :(得分:5)

首先:在这种情况下使用一个集合有点奇怪(对于Validated[..., Double]值的集合)。您关心Set语义的哪一部分?无秩序?独特吗?

通常,总结具有Monoid实例的元素的最直接方法是对带有combineAll实例的事物使用Foldable方法,例如{{1} }(而不是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)) ,因为Cats为SortedSet提供了一个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运算符用于monoid:

|+|

总结:您无法直接在scala> values.fold(Validated.valid(0.0))(_ |+| _) res4: cats.data.ValidatedNel[String,Double] = Valid(3.0) 上致电combineAll,因为Cats并未为Set提供Foldable。我建议您在任何情况下都应重新考虑使用Set,但是如果您决定坚持使用它,则可以选择以下几种方法:像我一样转换为SetList上面,在SortedSet上使用标准fold,或者最终编写自己的Set或使用来自胡同的动物。