scala - 如何对 Set[ValidatedNel[String, Double]] 求和?
问题描述
我有这个:
Set[ValidatedNel[String, Double]]
我想将其中的双打相加得到:
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))
}
我无法创建经过验证的NelNumeric ...
解决方案
首先:在这种情况下使用集合(用于值集合)感觉有点奇怪Validated[..., Double]
。Set
你关心语义的哪一部分?无序?独特性?
一般来说,总结具有实例的元素最直接的方法Monoid
是使用combineAll
具有实例的事物的方法Foldable
——例如 a 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
直接调用 your Set
,因为 Cats 不提供Foldable
for Set
。我建议Set
在任何情况下都仔细考虑您对的使用,但是如果您决定坚持使用它,您有几个选择:转换为List
或SortedSet
像我上面一样,使用标准fold
,Set
或者最后编写自己的Foldable[Set]
或使用一只来自alleycats。
推荐阅读
- java - 尝试将 B+Tree 中的元素添加到 ArrayList 时出现 OutOfMemoryError
- python - 过期后如何自动重新获取Python脚本中的访问令牌?
- python - Python 输入文本到随机更改的元素,没有 id 或 name
- typescript - 在打字稿中定义一个扩展抽象类的属性类型
- flutter - 除了从这里到那里,我如何打印?
- vb.net - 如何使用 VB.NET UDPClient 接收 UDP 数据报
- r - 如何在R中制作范围图?
- database - 在 Photoshop 中将数据集导出为 jpg 文件
- python - 基于多个属性对类进行排序
- class - 有没有办法指定模板参数类型必须从特定的基类派生?