折叠/展平猫Seq / cats.Validated列表

时间:2017-12-12 21:36:40

标签: scala scala-cats

我所拥有的是List[Validated[NonEmptyList[ErrorType], T]],我希望将其扁平化为Validated[NonEmptyList[ErrorType], T]

我的不良尝试是收集所有错误,然后再制作一个新错误。

val errors = validations collect {
   case Invalid(errs) => errs.toList
}
if (errors.nonEmpty) Invalid(NonEmptyList.fromListUnsafe(errors.flatten)) else Valid(t)

我已经尝试了foldMaptraverse,但是我遇到了问题,我在范围内没有Monoid,我觉得猫可能会开箱即用在一个班轮。

有些older answers on this kind of question似乎已过时(或者至少我找不到他们所指的功能)。

更新

我已经修好了这个类型。

3 个答案:

答案 0 :(得分:1)

要回答您的问题this example uses kind projector compiler plugin for partial application of type parameters。根据您对Scala术语的熟悉程度,这可能不完全合理。基本上它意味着一些Scala方法需要某个形状的参数,并且你必须通过在适当的位置添加一个问号来帮助编译器。

还要确保添加一些导入。

import cats._
import cats.data._
import cats.implicits._
import Validated.{ valid, invalid }

然后给出,

val a = valid[String,Int](1)
val as = List(a)

您可以使用List.sequenceList[Validated[NonEmptyList[E, T]]]转换为Validated[E, List[T]]

as.sequence[Validated[String,?], Int]

在这种情况下,如果使用单个String作为错误类型,则表示错误类型的字符串将连接在一起形成一个字符串。这是monoid约束来自你提到的 - 它有助于将字符串与字符串连接组合在一起。其他错误类型也可能有效,例如错误类型为List[String]List[ErrorType],而不是简单的String。如果要累积错误,请使用某种错误类型的列表

val a = valid[List[String],Int](1)
val b = invalid[List[String], Int]("some".lift[List])
List(a,b).sequence[Validated[List[String],?], Int]

结果

res29: Validated[List[String], List[Int]] = Invalid(List("some"))

上面需要提升操作从String到String列表。

答案 1 :(得分:1)

如果你正在使用sbt-partial-unificationuses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" 编译器标志(你应该使用),你可以使用:

-Ypartial-unification

这是不安全的(只有在验证列表不为空时才有效)。 现在,如果您先构造实例,然后再验证它:

validation.sequence.map(_.head)

你仍然拥有它,你可以直接提供它:

val t: T = ???

val validation: List[Validated[NonEmptyList[ErrorType], T]] = 
   List(checkQuantities, checkName, checkConsisteny).map(f => f(t))

答案 2 :(得分:1)

我昨天刚刚遇到了类似的问题。这就是我解决它的方式(我使用的是Scala 2.12和Cats 1.1.0):

import cats.Traverse
import cats.data.{NonEmptyList, Validated}

val list: List[Validated[NonEmptyList[ErrorType], T]] = ...

import cats.instances.list._
val validated: Validated[NonEmptyList[ErrorType], List[T]] = Traverse[List].sequence(list)

这不是你想要的,因为这会将结构展平为List[A]而不是A。为了将A展平为相同类型,您可能需要在某处实现Monoid[A]方法的combine