Tôi nghĩ rằng sử dụng &&
để thực hiện có điều kiện là một thói quen xấu. Chắc chắn nó chỉ là một vấn đề lý do để làm điều này cho tác dụng phụ miễn phí các công cụ như False && all (/=0) [1..]
, nhưng khi có những tác dụng phụ nó khá lộn xộn để làm cho họ phụ thuộc vào một cách ẩn như vậy. (Vì thực hành quá phổ biến, hầu hết các lập trình viên sẽ ngay lập tức nhận ra nó, nhưng tôi không nghĩ đó là điều chúng ta nên khuyến khích, ít nhất không phải trong Haskell.)
Những gì bạn muốn là một cách để diễn đạt: "thực hiện một số hành động, cho đến một sản lượng False
".
Ví dụ đơn giản của bạn, tôi chỉ muốn làm điều đó một cách rõ ràng:
main = do
e0 <- run "foo"
when e0 $ run "bar"
hay ngắn: run "foo" >>= (`when` run "bar")
.
Nếu bạn muốn sử dụng rộng rãi hơn, bạn nên làm điều đó một cách tổng quát hơn. Đơn giản chỉ cần kiểm tra một điều kiện boolean không phải là rất chung chung, bạn sẽ thường cũng muốn vượt qua trên một số loại kết quả. Thông qua kết quả là lý do chính chúng tôi sử dụng một đơn nguyên cho IO, thay vì chỉ đơn giản là danh sách các hành động nguyên thủy.
Aha, monads! Thật vậy, những gì bạn cần là IO monad, nhưng với một "kill switch" bổ sung: hoặc bạn thực hiện một chuỗi các hành động, có thể với một số kết quả để vượt qua, hoặc - nếu bất kỳ lỗi nào trong số đó thất bại - bạn hủy bỏ toàn bộ điều. Nghe có vẻ giống như Maybe
, phải không?
http://www.haskell.org/hoogle/?hoogle=MaybeT
import Control.Monad.Trans.Maybe
run :: String -> MaybeT IO()
run s = MaybeT $ do
e <- system s
return $ if exitCodeToBool e then Just() else Nothing
main = runMaybeT $ do
run "foo"
run "bar"
Xem định nghĩa của 'liftM2'. Bạn cần một phiên bản đơn thuần của '(&&)' có độ nghiêm ngặt (monadic) mà bạn muốn. – augustss
Bạn nói rằng bạn muốn chạy các lệnh song song và chạy "bar" chỉ khi "foo" thành công. Không có nghĩa lý gì. Quyết định, bạn muốn nó song song hoặc tuần tự? – remdezx