将List [String]转换为函数中的ValidationNEL [String,A]

Mad*_*Dog 8 types scala scalaz

我有一个具有以下签名的功能

def reject[A](errors: List[String]): ValidationNEL[String, A]
Run Code Online (Sandbox Code Playgroud)

由于这是拒绝方法,因此A永远不会返回类型,但我需要反映它以匹配签名.我正在弄乱类型lambdas以获得我想要的结果,如下所示:

errors.map(Failure[String, A](_).liftFailNel).sequence[({type l[a] = ValidationNEL[String, a]})#l, A]
Run Code Online (Sandbox Code Playgroud)

这使用类型List[A](或似乎),而不是我想要的类型A.有没有一种标准的方法来推导出我想要的结果?

Ben*_*mes 5

因为errors可能是空的List,并且你限制自己没有类型的值A,我认为你不能把它写成一个总函数.要编写此类型签名,您需要通过假装空列表案例来作弊,例如

def reject[A](errors: List[String]): ValidationNEL[String, A] =
  Failure(errors.toNel.get) // bad!
Run Code Online (Sandbox Code Playgroud)

编辑:正如Apocalisp指出的那样,你可以通过为空列表引入一个错误来使它成为一个完整的函数.但我只会errors在运行时计算,我怀疑这不是你的用例,因为它会导致愚蠢的错误,例如:

def reject[A](errors: List[String]): ValidationNEL[String, A] =
  Failure(errors.toNel getOrElse NonEmptyList("Error: There were no errors!"))
Run Code Online (Sandbox Code Playgroud)

为什么不把它errors作为一个NonEmptyList代替 - 如果你在编译时有错误,大概只使用这个函数.

def reject[A](errors: NonEmptyList[String]): ValidationNEL[String, A] =
  Failure(errors)
Run Code Online (Sandbox Code Playgroud)

您可以通过复制签名NonEmptyList.apply(并将其专门化String)来使用这个terser :

def reject[A](h: String, t: String*): ValidationNEL[String, A] =
  Failure(NonEmptyList(h, t: _*))
Run Code Online (Sandbox Code Playgroud)

我们来试试吧:

scala> reject("foo", "bar", "baz")
res0: scalaz.package.ValidationNEL[String,Nothing] = Failure(NonEmptyList(foo, bar, baz))
Run Code Online (Sandbox Code Playgroud)