Trong Haskell, tôi có thể sử dụng kiểu a -> Maybe b
để mô hình hóa một hàm trả về giá trị của kiểu b
hoặc không trả về gì (nó không thành công).
Nếu tôi có các loại a1, ..., a(n+1)
và chức năng f1, ..., fn
, với fi :: ai -> Maybe a(i+1)
cho tất cả i
, 1 <= i <= n
tôi có thể chuỗi các chức năng bằng cách sử dụng các >>=
nhà điều hành của các Maybe
đơn nguyên, ghi:
f1 x >>= f2 >>= f3 >>=... >>= fn
Các >>=
Đảm bảo hành mà mỗi chức năng được áp dụng càng lâu càng tiền nhiệm của nó đã trở lại một giá trị có ý nghĩa. Ngay khi một chức năng trong chuỗi thất bại, toàn bộ chuỗi thất bại (trả về Nothing
) và các chức năng tiếp theo trong chuỗi không được đánh giá.
Tôi có một mô hình hơi giống nhau trong đó tôi muốn thử một số chức năng trên cùng một đầu vào và quay lại ngay khi một chức năng thành công . Nếu tất cả các hàm thất bại (trả về Nothing
), toàn bộ tính toán sẽ thất bại. Chính xác hơn, tôi có chức năng f1, ..., fn :: a -> Maybe b
và tôi xác định chức năng
tryFunctions :: [a -> Maybe b] -> a -> Maybe b
tryFunctions [] _ = Nothing
tryFunctions (f : fs) x = case f x of
Nothing -> tryFunctions fs x
r@(Just _) -> r
Theo một nghĩa nào đó, điều này là kép đối với Maybe
đơn nguyên ở chỗ một tính toán dừng lại ở thành công đầu tiên thay vì ở thất bại đầu tiên.
Tất nhiên, tôi có thể sử dụng chức năng mà tôi đã viết ở trên nhưng tôi đã tự hỏi liệu có cách nào tốt hơn, được thiết lập tốt và thành ngữ để thể hiện mẫu này trong Haskell không.
Alternative
toán tử infix biểu tượng <|>
và được định nghĩa theo thuật ngữ Monoid
return f1 ?? f2 ?? f3 ?? DefaultValue;