2012-06-23 31 views
9

Tôi khá mới đối với scalaz và tôi đã bắt đầu với xác thực.Làm phẳng xác nhận hợp lệ Scalaz

Tôi có một số chức năng xác nhận có dạng:

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

tôi sau đó sử dụng phong cách applicative để kết hợp nhiều hợp lệ và sau đó gọi một chức năng mà cũng trả về một xác nhận:

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

ở đâu,

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

Tuy nhiên, khi gọi loại kết quả ở trên là:

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

tôi có thể giải nén này bằng cách gọi gấp về kết quả với hai chức năng, người đầu tiên mà chỉ truyền các NEL như một thất bại và đó thứ hai chỉ truyền đối số của nó:

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] 

này hoạt động và trả về các loại và kết quả chính xác. Tuy nhiên nó không cảm thấy như giải pháp chính xác vì vậy tôi phải mất một cái gì đó. Tôi cần phải làm gì để tránh nếp gấp kinh khủng này ở cuối?

Trả lời

8

Điều bạn đang tìm kiếm ở đây là monoic join.

Điều này là không thực sự là một đơn nguyên, vì mặt lỗi mang cấu trúc Semigroup không thể được giữ nguyên bởi Monad. Nhưng bạn luôn có thể thả xuống đơn vị Either nếu cần. Chức năng này được cung cấp bởi flatMap.

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

Nếu bạn có một lỗi ở bên ngoài, kết quả sẽ là lỗi đó. Nếu bạn có lỗi bên trong thành công, kết quả sẽ là lỗi bên trong. Nếu không thì kết quả sẽ thành công. Lưu ý rằng không thể có lỗi cả ở bên trong và bên ngoài. Đây là lý do tại sao bạn phải sử dụng Applicative thay vì Monad nếu bạn muốn kết hợp lỗi.

Các vấn đề liên quan