2013-02-18 10 views
5

Tôi là người mới bắt đầu trong công việc lập trình hàm và tôi có một chuỗi ValidationNEL [A, B] và tôi muốn tích lũy các lỗi vào một ValidationNEL mới [A, B]. Điều này phụ thuộc vào thực tế rằng B là một cấu trúc dữ liệu có thể thay đổi được từ mã kế thừa, và do đó, nó sẽ quá tải để giữ Seq [B].Chỉ tích lũy các lỗi xác nhận trong Scalaz

Tôi biết từ bài viết khác cumulating lỗi và thành công là có thể thông qua các phương pháp trình tự: Processing a list of Scalaz6 Validation

Từ hiểu biết của tôi tất cả đi để viết một applicative phù hợp và có thể là một Traverse thích hợp.

trait MA[M[_], A] extends PimpedType[M[A]] with MASugar[M, A] { 

    def sequence[N[_], B](implicit a: A <:< N[B], t: Traverse[M], n: Applicative[N]): N[M[B]] = 
    traverse((z: A) => (z: N[B])) 

    def traverse[F[_],B](f: A => F[B])(implicit a: Applicative[F], t: Traverse[M]): F[M[B]] = 
    t.traverse(f, value) 
    } 

Làm cách nào để bắt đầu? Khi tôi cố gắng xem xét mã nguồn Scalaz để tìm hiểu cách thực hiện Ứng dụng của tôi, tôi đã vô cùng bối rối. Tôi thậm chí không thể tìm ra ứng dụng nào cho phép tích lũy cả thất bại lẫn thành công trong Xác thực.

+0

Bạn đang cố gắng để đi từ Seq [ValidtionNEL [A, B]] để ValidationNEL [A, Seq [B]] hoặc một cái gì đó tương tự? – Noah

+0

không từ Seq [ValidtionNEL [A, B]] tới ValidationNEL [A, B] – Edmondo1984

+0

Vì vậy ValidationNEL chỉ là Validation [NonEmptyList [A], B] nên bạn không thể làm những gì bạn yêu cầu trừ khi bạn có thể thêm B cùng nhau (ints , danh sách, v.v.) – Noah

Trả lời

3

muộn để đảng, nhưng như của Scalaz 7.0.4, chúng ta có thể làm điều này:

def takeLastSuccess[A, B](seq: Seq[ValidationNel[A, B]]) = { 
     implicit val useLast = Semigroup.lastSemigroup[B] 
     seq reduceLeft (_ +++ _) 
    } 
2

Bây giờ tôi hiểu câu hỏi của bạn tốt hơn một chút, điều này là khá thẳng về phía trước:

def takeLastSuccess[A, B](seq:Seq[ValidationNEL[A, B]]) = 
    seq.sequence[({type l[a] = ValidationNEL[A, a]})#l, B].map(_.last) 

Khi bạn trình tự Scala này có một số rắc rối với các loại, do đó bạn cần phải sử dụng một loại lambda. Trình tự là một phím tắt đẹp để chuyển từ Seq [Something [X]] thành Something [Seq [X]]. Cuối cùng, chúng tôi chỉ lập bản đồ thành công và lấy B cuối cùng từ chuỗi B.

Đi ra khỏi ví dụ từ the post you cited, đây là những gì tôi nhận được từ REPL:

scala> import scalaz._, Scalaz._ 
import scalaz._ 
import Scalaz._ 

scala> type ExceptionsOr[A] = ValidationNEL[Exception, A] 
defined type alias ExceptionsOr 

scala> val successResults: Seq[ExceptionsOr[Int]] = Seq(
    |  "13".parseInt.liftFailNel, "42".parseInt.liftFailNel 
    | ) 
successResults: Seq[ExceptionsOr[Int]] = List(Success(13), Success(42)) 

scala> val failResults: Seq[ExceptionsOr[Int]] = Seq(
    |  "13".parseInt.liftFailNel, "a".parseInt.liftFailNel, "b".parseInt.liftFailNel 
    | ) 
failResults: Seq[ExceptionsOr[Int]] = List(Success(13), Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "a")), Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "b"))) 

scala> def takeLastSuccess[A, B](seq:Seq[ValidationNEL[A, B]]) = seq.sequence[({type l[a] = ValidationNEL[A, a]})#l, B].map(_.last) 
takeLastSuccess: [A, B](seq: Seq[scalaz.Scalaz.ValidationNEL[A,B]])scalaz.Validation[scalaz.NonEmptyList[A],B] 

scala> takeLastSuccess(successResults) 
res0: scalaz.Validation[scalaz.NonEmptyList[Exception],Int] = Success(42) 

scala> takeLastSuccess(failResults) 
res1: scalaz.Validation[scalaz.NonEmptyList[Exception],Int] = Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "a", java.lang.NumberFormatException: For input string: "b")) 
+0

Đây là giải pháp tương tự với những gì tôi đã thực hiện. Giải pháp lý tưởng sẽ là cung cấp một Ứng dụng đúng cho phương pháp trình tự hoạt động như tôi mong muốn – Edmondo1984