我是函数式编程工作的初学者,我有一系列ValidationNEL [A,B],我希望将错误累积到新的ValidationNEL [A,B]中。这取决于B的事实 是一个来自遗留代码的可变数据结构,因此持有Seq [B]会过于宽泛。
我从其他帖子中了解到,通过序列方法可以累积错误和成功:Processing a list of Scalaz6 Validation
根据我的理解,一切都来写一个正确的Applicative,也许是一个正确的Traverse。
trait MA[M[_], A] extends PimpedType[M[A]] with MASugar[M, A] {
def sequence[N[_], B](implicit a: A <:< N[B], t: Traverse[M], n: Applicative[N]): N[M[B]] =
traverse((z: A) => (z: N[B]))
def traverse[F[_],B](f: A => F[B])(implicit a: Applicative[F], t: Traverse[M]): F[M[B]] =
t.traverse(f, value)
}
我该如何开始?当我试图查看Scalaz源代码以了解如何实现我的Applicative时,我非常困惑。我甚至无法找出哪个应用程序允许在验证中累积失败和成功。
答案 0 :(得分:3)
晚会,但从Scalaz 7.0.4开始,我们可以这样做:
def takeLastSuccess[A, B](seq: Seq[ValidationNel[A, B]]) = {
implicit val useLast = Semigroup.lastSemigroup[B]
seq reduceLeft (_ +++ _)
}
答案 1 :(得分:2)
现在我对你的问题了解得更好了,这很简单:
def takeLastSuccess[A, B](seq:Seq[ValidationNEL[A, B]]) =
seq.sequence[({type l[a] = ValidationNEL[A, a]})#l, B].map(_.last)
当你对这个Scala进行排序时,这些类型有一些问题,所以你需要使用一个类型lambda。序列是从Seq [Something [X]]到Something [Seq [X]]的一个很好的快捷方式。最后,我们只是映射成功并从B的序列中获取最后一个B.
从the post you cited取消示例,这是我从REPL获得的内容:
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> type ExceptionsOr[A] = ValidationNEL[Exception, A]
defined type alias ExceptionsOr
scala> val successResults: Seq[ExceptionsOr[Int]] = Seq(
| "13".parseInt.liftFailNel, "42".parseInt.liftFailNel
| )
successResults: Seq[ExceptionsOr[Int]] = List(Success(13), Success(42))
scala> val failResults: Seq[ExceptionsOr[Int]] = Seq(
| "13".parseInt.liftFailNel, "a".parseInt.liftFailNel, "b".parseInt.liftFailNel
| )
failResults: Seq[ExceptionsOr[Int]] = List(Success(13), Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "a")), Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "b")))
scala> def takeLastSuccess[A, B](seq:Seq[ValidationNEL[A, B]]) = seq.sequence[({type l[a] = ValidationNEL[A, a]})#l, B].map(_.last)
takeLastSuccess: [A, B](seq: Seq[scalaz.Scalaz.ValidationNEL[A,B]])scalaz.Validation[scalaz.NonEmptyList[A],B]
scala> takeLastSuccess(successResults)
res0: scalaz.Validation[scalaz.NonEmptyList[Exception],Int] = Success(42)
scala> takeLastSuccess(failResults)
res1: scalaz.Validation[scalaz.NonEmptyList[Exception],Int] = Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "a", java.lang.NumberFormatException: For input string: "b"))