2012-06-23 6 views
9

私はscalazをかなり新しくしており、検証から始めました。ネストされたScalaz検証を平準化する

(validateXyz(...) |@| validateAbc(...)) { (first, second) => 
    otherFunction(first, second) 
} 

:私は、複数の検証を組み合わせ、その後も検証を返す別の関数を呼び出すために応用的なスタイルを使用してい

def validateXyz(...): ValidationNEL[String, String] = ... 

私は、フォームの一部の検証機能を持っていますここで、

def otherFunction(first: String, second: String): ValidationNEL[String, String] = ... 

ただし、上記の結果の型次のとおりです。

val result: ValidationNEL[String, ValidationNEL[String, String]] = ... 

私は2つの機能、ただ単にその引数を伝搬する失敗と第二としてNELを伝搬する最初に結果に折り目を呼び出すことによって、これを解凍することができます

def propagateF(result: NonEmptyList[String]): ValidationNEL[String, String] = result.fail 
def propagateV(result: ValidationNEL[String, String]) = result 

result.fold(propagateF, propagateV) 
// result type: ValidationNEL[String, String] 

この正しい型と結果を返します。しかし、それは正しい解決策のように感じないので、私は何かを欠いているに違いありません。最後にこの恐ろしい折り目を避けるためには何をする必要がありますか?

答えて

8

あなたが探しているものは、モナディーjoinです。

エラー側がMonadで保存できないSemigroup構造を持っているので、Validation自体は本当にモナドではありません。しかし、必要ならばいつでもEitherモナドに落とすことができます。この機能はflatMapによって提供されています。

(validateXyz(...) |@| validateAbc(...))(otherFunction).flatMap(x => x) 

外部にエラーがある場合は、そのエラーになります。成功の中にエラーがある場合、結果は内部エラーになります。それ以外の場合、結果は成功になります。内側と外側の両方にエラーが存在しないことに注意してください。。このため、エラーを組み合わせる場合は、MonadではなくApplicativeを使用する必要があります。

関連する問題