Đ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 Promise
và Validation
để 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
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
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]]' –