Scala 组合Seq[ValidatedNel]的有效值

Scala 组合Seq[ValidatedNel]的有效值,scala,scala-cats,Scala,Scala Cats,我有以下情况: case class MyString(str: String) val val1: ValidatedNel[String, MyString] = MyString("valid1").validNel val val2: ValidatedNel[String, MyString] = MyString("valid2").validNel val val3: ValidatedNel[String, MyString] = "invalid".invalidNel va

我有以下情况:

case class MyString(str: String)

val val1: ValidatedNel[String, MyString] = MyString("valid1").validNel
val val2: ValidatedNel[String, MyString] = MyString("valid2").validNel
val val3: ValidatedNel[String, MyString] = "invalid".invalidNel
val vals = Seq(val1, val2, val3)
//vals: Seq[cats.data.Validated[cats.data.NonEmptyList[String],MyString]] = List(Valid(MyString(valid)), Invalid(NonEmptyList(invalid)))
最后,我希望能够对结果进行
匹配
,并获得所有错误或所有有效值作为序列

我的问题是:如何将
Seq[Validated[NonEmptyList[String],MyString]]
转换为
Validated[NonEmptyList[String],Seq[MyString]]]]

因此,我的第一步是为
Seq[MyString]
实现
半群:

implicit val myStringsAdditionSemigroup: Semigroup[Seq[MyString]] = new Semigroup[Seq[MyString]] {
  def combine(x: Seq[MyString], y: Seq[MyString]): Seq[MyString] = x ++ y
}
。。。有效的方法是:

Seq(val1, val2).map(_.map(Seq(_))).reduce(_ |+| _)
//res0: cats.data.Validated[cats.data.NonEmptyList[String],Seq[MyString]] = Valid(List(MyString(valid1), MyString(valid2)))

但是我需要通过将所有有效值包装在
Seq
中来准备数据。。。这感觉很奇怪。那么,也许有更好的方法

如果您使用的不是
Seq
,如
Vector
List
,您可以
对其进行排序

sequence
基本上将类型构造函数从内到外转换。意思是把一个
F[G[a]]
变成一个
G[F[a]]
。要使其工作,
F
需要是一个
遍历
G
需要是一个
应用程序
。幸运的是,
Validated
是一个
应用程序
列表
向量
遍历
的实例

因此,最终您的代码应该如下所示:

import cats.implicits._

val validatedList: Validated[NonEmptyList[String],List[MyString]]] = 
  vals.sequence
注意:如果这不能为您编译,您可能需要启用
部分统一

启用
部分统一
的最简单方法是添加
sbt部分统一

如果您使用的是Scala 2.11.9或更高版本,还可以简单地添加编译器标志:

scalacOptions += "-Ypartial-unification"

我们来自
cats
团队,强烈建议您在使用cats时始终打开此标志,因为它使一切变得更加简单。

如果您使用的不是
Seq
,如
Vector
List
,您可以
对其进行排序

sequence
基本上将类型构造函数从内到外转换。意思是把一个
F[G[a]]
变成一个
G[F[a]]
。要使其工作,
F
需要是一个
遍历
G
需要是一个
应用程序
。幸运的是,
Validated
是一个
应用程序
列表
向量
遍历
的实例

因此,最终您的代码应该如下所示:

import cats.implicits._

val validatedList: Validated[NonEmptyList[String],List[MyString]]] = 
  vals.sequence
注意:如果这不能为您编译,您可能需要启用
部分统一

启用
部分统一
的最简单方法是添加
sbt部分统一

如果您使用的是Scala 2.11.9或更高版本,还可以简单地添加编译器标志:

scalacOptions += "-Ypartial-unification"

来自
cats
团队的我们强烈建议您在使用cats时始终打开此标志,因为它使一切变得更加简单。

我尝试在其中使用的项目是一个maven项目。这是否意味着无法启用部分统一并因此使用此功能?不,您可以很好地使用它们,只需将编译器参数放入
中,它应该位于
:)我试图在其中使用的项目是一个maven项目。这是否意味着无法启用部分统一并因此使用此功能?不,您可以很好地使用它们,只需将编译器参数放在
中,它应该放在
中:)