Các liftM2 combinator có thể được sử dụng trong Reader monad để làm điều này theo cách 'chức năng hơn':
import Control.Monad
import Control.Monad.Reader
-- ....
filter (liftM2 (&&) odd (> 100)) [1..200]
Lưu ý rằng nhập khẩu là quan trọng; Control.Monad.Reader cung cấp cá thể Monad (e ->) mà làm cho tất cả các công việc này.
Lý do hoạt động này là đơn vị đọc chỉ là (e ->) đối với một số môi trường e. Do đó, một biến vị ngữ boolean là một hàm đơn thuần 0-ary trả về bool trong một môi trường tương ứng với đối số của nó. Sau đó chúng tôi có thể sử dụng liftM2 để phân phối môi trường trên hai vị từ như vậy.
Hoặc, trong điều kiện đơn giản, liftM2 sẽ đóng vai trò một chút như thế này khi các loại hoạt động ra:
liftM2 f g h a = f (g a) (h a)
Bạn cũng có thể định nghĩa một combinator mới nếu bạn muốn để có thể chuỗi những cách dễ dàng, và/hoặc không muốn gây rối với liftM2:
(.&&.) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(.&&.) f g a = (f a) && (g a)
-- or, in points-free style:
(.&&.) = liftM2 (&&)
filter (odd .&&. (> 5) .&&. (< 20)) [1..100]
Cả hai ví dụ làm việc trên GHC 7.6.3 thậm chí nếu bạn không nhập 'Control.Monad.Reader'. – sjakobi
Tôi 'liftM2' có thể (ngày nay) được thay thế như thế này:' filter ((&&) <$> lẻ <*> (> 100)) [1.200] '. Đó là như nhau, nhưng đẹp hơn. :) Nó cũng chỉ yêu cầu 'Control.Applicative', và không có monads đầy đủ. … Mặc dù tôi vẫn tự hỏi toán tử nào cho phép ANDING nhiều hơn hai hàm Boolean… – Evi1M4chine