从聚合的ValidationNel

时间:2015-09-24 16:15:58

标签: scala scalaz

是否可以使用ValidationNel返回错误和成功的混合?

所以举个例子:

def f(i: Int) =
  if (i > 2) i.successNel
  else "something wrong".failureNel

List(1, 2, 3).traverseU(f) // Failure(NonEmptyList(something wrong, something wrong))

借用How to use Scalaz's traverse and traverseU with Either我们得到两次失败(1,2)和一次成功(3)。由于我们有超过0次失败,结果是失败,但有没有办法从3获取成功或者是否被扔掉?

2 个答案:

答案 0 :(得分:3)

如果你真的想要同时获得成功和失败,那么更简洁的方法是使用.separate

import scalaz.syntax.validation._
import scalaz.syntax.monadPlus._
import scalaz.std.list._

@ val a = "yeah".success[Int]
a: Validation[Int, String] = Success(yeah)
@ val b = "wot".success[Int]
b: Validation[Int, String] = Success(wot)
@ val c = 10.failure[String]
c: Validation[Int, String] = Failure(10)
@ List(a,b,c).separate
res6: (List[Int], List[String]) = (List(10), List("yeah", "wot"))

答案 1 :(得分:2)

修改:从@melps answer查看separate MonadPlus

Validation[E, X]ValidationNel[E, X]或scalaz的分离Try相比,您使用Either,因此\/也可以traverse进行错误积累。第一次失败。

map功能是sequenceList(1, 2, 3).map(f).sequenceU == List(1, 2, 3).traverseU(f) 的组合。

List(1, 2, 3).map(f)
// List[scalaz.Validation[scalaz.NonEmptyList[String],Int]] = 
// List(Failure(NonEmptyList(something wrong)), 
//   Failure(NonEmptyList(something wrong)), 
//   Success(3))

如果我们看一下map之后的中间结果:

Validation[NonEmptyList[String], Int]]

我们可以看到我们的中间结果属于ValidationNel[String, Int]类型,等于sequence

如果我们再查看最后一步(sequence):

  • F[G[_]] => G[F[_]]是一个将monad翻出来的功能(List[ValidationNel[String, Int]]),在这种情况下,我们从ValidationNel[String, List[Int]]转到Validation
  • sequence的上下文是我们想知道我们的函数是否成功以及未能累积所有错误的情况。

因此,使用<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/iposLite?zeroDateTimeBehavior=convertToNull</property> <property name="hibernate.connection.username">root</property> <mapping class="com.isimple.intelijpos_lite.models.Grn" /> <mapping class="com.isimple.intelijpos_lite.models.GrnDetail" /> <mapping class="com.isimple.intelijpos_lite.models.GrnRetrunDetail" /> <mapping class="com.isimple.intelijpos_lite.models.GrnReturn" /> <mapping class="com.isimple.intelijpos_lite.models.Invoice" /> <mapping class="com.isimple.intelijpos_lite.models.InvoiceDetail" /> <mapping class="com.isimple.intelijpos_lite.models.InvoiceReturn" /> <mapping class="com.isimple.intelijpos_lite.models.InvoiceReturnDetail" /> <mapping class="com.isimple.intelijpos_lite.models.Item" /> <mapping class="com.isimple.intelijpos_lite.models.Ledger" /> <mapping class="com.isimple.intelijpos_lite.models.LedgerDetail" /> <mapping class="com.isimple.intelijpos_lite.models.Receipt" /> <mapping class="com.isimple.intelijpos_lite.models.Stock" /> <mapping class="com.isimple.intelijpos_lite.models.Supplier" /> <mapping class="com.isimple.intelijpos_lite.models.User" /> </session-factory> </hibernate-configuration> 我们会丢失有关列表中哪些元素成功的信息。