2013-06-04 26 views
2

無法弄清楚是否可以使用Scalaz 7寫這樣的東西。我試圖用代碼塊中的註釋表達自己。如何使用應用仿函數來結合Scalaz驗證

def validate1(p: String) = ValidationNel[String, Value] = ... 
def validate2(p: String) = ValidationNel[String, Value] = ... 

validateCombination(p1: String, p2: String) = { 
    // I would like to write something like 
    (validate1(p1) |@| validate2(p2)) { (v1, v1) => 
    // And validate the combinations here and return successNel of failNel 
    } 
} 

def validate(p1: String, p2: String, p3: String) = { 
    (validateCombination(p1, p2) |@| validate1(p3)) { (v1, v2, v3) => 
    // Notice the three parameters I want to have here 
    } 
} 

我剛剛結束了在validateCombinations不同類型混淆編譯錯誤,或者對適用函子僅有2參數我進去驗證功能,ValidationNel型[...]的其中一個之中。

回答

6

你可以使用.flatMap(identity)的方法validateCombination生產ValidationNel[String, (Value, Value)]pattern matching的方法validate這樣的:

def validateCombination(p1: String, p2: String): ValidationNel[String, (Value, Value)] = { 
    // I would like to write something like 
    (validate1(p1) |@| validate2(p2)) { (v1, v1) => 
    (v1, v2).successNel[String] 
    }.flatMap(identity) 
} 

def validate(p1: String, p2: String, p3: String) = { 
    (validateCombination(p1, p2) |@| validate1(p3)) { case ((v1, v2), v3) => 
    // Notice the three parameters I want to have here 
    } 
} 

flatMap(身份)

通常你會使用嵌套容器的方法flatten得到M[T]M[M[T]]。它適用於Future,Option,Try,收藏等。

在這種情況下type M[T] = ValidationNel[String, T]

我不知道爲什麼沒有方法flattenValidation,但你總是可以使用flatMap(identity)代替flatten

匹配

作爲Ben JamesnotedflatMapValidation是可疑。你總是可以使用match代替它:

(validate1(p1) |@| validate2(p2)) { (v1, v1) => 
    (v1, v2).successNel[String] 
} match { 
    case Success(s) => s 
    case Failure(f) => Failure(f) 
} 

模式匹配

模式匹配處理的元組的常用方法。例如,它與foldLeft方法有所不同,如foldLeft(1 -> 2){ case ((a, b), c) => ??? }

如果您發現自己在Tuple上使用獲得者_N,那麼您可能應該使用模式匹配。

的理解

至於Daniel C. Sobralnoted的理解可能更容易理解。

你可以用它在你的validate方法是這樣的:

def validate(p1: String, p2: String, p3: String) = { 
    for{ 
    (v1, v2) <- validateCombination(p1, p2) // pattern matching 
    v3 <- validate1(p3) 
    } yield ??? // Your code here 
} 

它涉及模式匹配,而不case關鍵字。

注意,對於修真呼籲validateCombination(p1, p2)flatMap,所以你會從validate1(p3)的情況下,失去了錯誤信息validateCombination(p1, p2)Failure。相反,|@|收集來自雙方的所有錯誤消息。

+0

雖然我會用理解 - 這更容易理解,恕我直言。 –

+0

「驗證」並不平坦,因爲它不打算有單子。實際上,'flatMap'方法是可疑的。但是有一些方法可以在驗證的等價物上運行操作,並再次轉換回來,例如'v.disjunctioned(_。flatten)' –

+0

@ DanielC.Sobral:你的意思是「理解而不是'| @ |'」?我認爲重點是保持'| @ |'不變。感謝您的建議。你介意我將它添加到我的答案? – senia