2013-01-09 82 views
8

是否有一種慣用的方式來處理Scalaz6中的驗證集合?處理Scalaz6驗證列表

val results:Seq[Validation[A,B]] 
val exceptions = results.collect{case Failure(exception)=>exception} 
exceptions.foreach{logger.error("Error when starting up ccxy gottware",_)} 
val success = results.collect{case Success(data)=>data} 
success.foreach {data => data.push} 
if (exceptions.isEmpty) 
    containers.foreach(_.start()) 

我可以考慮在循環結果時使用摺疊,但最終測試呢?

回答

9

處理驗證列表的常用方法是使用sequence將列表變成Validation[A, List[B]],如果沿途出現任何錯誤,該列表將爲空(即,爲Failure)。

排序一個Validation在左邊類型的半羣中累積錯誤(與立即失敗的Either相對)。這就是爲什麼你經常看到ValidationNEL(其中NEL代表NonEmptyList)而不是簡單地使用Validation。因此,舉例來說,如果你有這樣的結果類型:

import scalaz._, Scalaz._ 

type ExceptionsOr[A] = ValidationNEL[Exception, A] 

而且一些成果:

val results: Seq[ExceptionsOr[Int]] = Seq(
    "13".parseInt.liftFailNel, "42".parseInt.liftFailNel 
) 

測序會給你以下幾點:

scala> results.sequence 
res0: ExceptionsOr[Seq[Int]] = Success(List(13, 42)) 

如果我們有一些象這樣的錯誤,另一方面:

val results: Seq[ExceptionsOr[Int]] = Seq(
    "13".parseInt.liftFailNel, "a".parseInt.liftFailNel, "b".parseInt.liftFailNel 
) 

我們會最終有一個Failure(請注意,我重新格式化輸出,使其易讀這裏):

scala> results.sequence 
res1: ExceptionsOr[Seq[Int]] = Failure(
    NonEmptyList(
    java.lang.NumberFormatException: For input string: "a", 
    java.lang.NumberFormatException: For input string: "b" 
) 
) 

所以你的情況,你會寫是這樣的:

val results: Seq[ValidationNEL[A, B]] 

results.sequence match { 
    case Success(xs) => xs.foreach(_.push); containers.foreach(_.start()) 
    case Failure(exceptions) => exceptions.foreach(
    logger.error("Error when starting up ccxy gottware", _) 
) 
} 

更多關於sequenceValidation的更多信息,請參閱我的回答herehere

+0

免費的情況如何?如果至少驗證成功了,我想成功嗎? – Edmondo1984

+0

這聽起來像你可能正在對'驗證'的穀物工作。在7中,你可以用'|||'減少列表,但是在6中,你需要像使用半羣的總和來使'Either'正確投影(或者你可以寫自己的'|||')。 –

+0

你能指點我解釋什麼是半羣的資源嗎? – Edmondo1984