2012-06-10 14 views
7

Đang viết thư viện hoàn toàn không đồng bộ để truy cập dịch vụ từ xa (sử dụng Play2.0), tôi đang sử dụng PromiseValidation để tạo cuộc gọi không chặn, có loại trình bày không thành công và kết quả hợp lệ cùng một lúc.Tính toán không đồng bộ với Xác thực trong Scala bằng Scalaz

Promise đến từ Play2-scala, trong đó Validation xuất phát từ scalaz.

Vì vậy, đây là loại ví dụ về các chức năng như vậy

  • f :: A => Promise[Validation[E, B]]
  • g :: B => Promise[Validation[E, C]]

Cho đến nay, tốt như vậy, bây giờ nếu tôi muốn soạn chúng , Tôi có thể đơn giản sử dụng thực tế là Promise trình bày một flatMap, vì vậy tôi có thể làm điều đó với một hiểu biết

for (
    x <- f(a); 
    y <- g(b) 
) yield y 

Ok, tôi đã thực hiện một lối tắt cho vấn đề của mình ở đây vì tôi không sử dụng lại kết quả Validation trong phạm vi hiểu. Vì vậy, nếu tôi muốn sử dụng lại x trong g, đây là làm thế nào tôi có thể làm

for (
    x <- f(a); // x is a Validation 
    y <- x.fold(
     fail => Promise.pure(x), 
     ok => g(ok) 
    ) 
) yield y 

Hội chợ đủ, nhưng loại này của soạn sẵn sẽ đi đến gây ô nhiễm mã của tôi hơn và hơn nữa. Vấn đề ở đây là tôi có một loại cấu trúc Monadic hai cấp như M[N[_]].

Ở giai đoạn này, là có bất kỳ cấu trúc trong f ° lập trình mà cho phép làm việc với cấu trúc như vậy bằng cách bỏ qua một cách dễ dàng mức secong:

for (
    x <- f(a); //x is a B 
    y <- g(b) 
) yield y 

Bây giờ, dưới đây là cách tôi đã đạt được một cái gì đó tương tự.

Tôi tạo ra loại cấu trúc monadic rằng kết thúc tốt đẹp mức hai trong một, chúng ta hãy nói ValidationPromised mà pimped loại Promise với hai phương pháp:

def /~> [EE >: E, B](f: Validation[E, A] => ValidationPromised[EE, B]): ValidationPromised[EE, B] = 
    promised flatMap { valid => 
     f(valid).promised 
    } 

def /~~>[EE >: E, B](f: A => ValidationPromised[EE, B]): ValidationPromised[EE, B] = 
    promised flatMap { valid => 
     valid.fold (
      bad => Promise.pure(KO(bad)), 
      good => f(good).promised 
     ) 
    } 

Điều này cho phép tôi làm những việc như vậy

 endPoint.service /~~>         //get the service 
     (svc =>             //the service 
     svc.start /~~> (st =>         //get the starting elt 
      svc.create(None) /~~>        //svc creates a new elt 
      (newE =>           //the created one 
      newEntry.link(st, newE) /~~>      //link start and the new 
      (lnk => Promise.pure(OK((st, lnk, newE))))  //returns a triple => hackish 
     ) 
     ) 
    ) 

Như chúng ta có thể thấy /~~> là khá giống với flatMap nhưng bỏ qua một cấp. Vấn đề là sự rầm rộ (đó là lý do tại sao "cho hiểu" tồn tại trong Scala và "làm" trong Haskell).

điểm khác, tôi đã là /~> mà đứng như một map cũng nhưng hoạt động trên cấp độ thứ hai (thay cho loại hợp lệ - thứ ba mức)

Vì vậy, câu hỏi thứ hai của tôi là hệ quả tất yếu để các cựu ... Tôi có chấp thuận một giải pháp bền vững với công trình này không?

xin lỗi để được lâu

+0

Tôi đã có ý định sử dụng ScalaZ với ứng dụng Play của mình trong một thời gian và đây là một cú huých tốt cho tôi. Tôi sẽ cho bạn biết làm thế nào tôi nhận được trên, và hy vọng sẽ có thể đặt một câu trả lời có ý nghĩa ở đây. – opyate

+0

Vâng! Cám ơn. Trên thực tế vấn đề thực sự không phải là sử dụng ScalaZ với Play. Đó là một câu hỏi tổng quát hơn (về f ° prog), bởi vì không có Play (vì vậy chỉ ScalaZ) tôi đã sử dụng 'IO' thay vì' Promise'. Do đó, tôi muốn có cùng một khuôn mẫu, đó là để nói: 'IO [Xác nhận [E, A]]' –

Trả lời

4

Khái niệm bạn đang tìm kiếm ở đây là monad transformers. Nói tóm lại, máy biến áp đơn nguyên bù cho monads not composing bằng cách cho phép bạn "xếp chồng" chúng.

Bạn đã không đề cập đến phiên bản Scalaz bạn đang sử dụng, nhưng nếu bạn nhìn vào scalaz-seven branch, bạn sẽ tìm thấy ValidationT. Điều này có thể được sử dụng để bọc bất kỳ F[Validation[E, A]] nào vào ValidationT[F, E, A], trong trường hợp của bạn là F = Promise. Nếu bạn thay đổi fg trở ValidationT, sau đó bạn có thể để lại mã của bạn như

for { 
    x ← f(a) 
    y ← g(b) 
} yield y 

này sẽ cung cấp cho bạn một ValidationT[Promise, E, B] như một kết quả.

+0

MMmh tìm loại điều tôi đang tìm kiếm !! Ok, vì vậy tôi sẽ cố gắng đầu tiên với biến đổi đơn nguyên của tôi, vì hai lý do vì đó là cách duy nhất để tìm hiểu, và thứ hai vì tôi đang ở trên nhánh 6.0.4. Và sau đó tôi có thể sẽ chuyển sang thứ 7 và tái cấu trúc cho ValidatorT ... Trong mọi trường hợp, tôi sẽ quay lại đây để nói thêm. Cảm ơn một lần nữa –

+0

Ok. Great doc. Tôi nhìn vào 'ValidationT' phương thức' flatMap' của nó thực sự là cái tôi cần (và đoán nó giống như '/ ~~>' của tôi). Nhưng để sử dụng nó trực tiếp, 'Promise' cần một thể hiện TypeClass của' Monad', mà nó không phải là doens't. Vì vậy, khi ScalaZ sẽ xuất hiện, tôi sẽ thực hiện nó để có thể sử dụng 'ValidationT' trực tiếp. –

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