liftM2 kombinator może być użyty w Monadzie Czytnika, aby zrobić to w "bardziej funkcjonalny" sposób:
import Control.Monad
import Control.Monad.Reader
-- ....
filter (liftM2 (&&) odd (> 100)) [1..200]
Należy pamiętać, że import jest ważny; Control.Monad.Reader zapewnia instancję Monad (e ->), która sprawia, że wszystko działa.
Powodem tego jest monada czytelnika po prostu (e ->) dla jakiegoś środowiska e. Zatem predykat boolowski jest 0-funkcyjną funkcją monadyczną zwracającą bool w środowisku odpowiadającym jej argumentowi. Następnie możemy użyć liftM2, aby rozdzielić środowisko na dwa takie predykaty.
Lub w prostszych słowach, liftM2 będzie działać trochę jak ten, gdy typy wypracowanie:
liftM2 f g h a = f (g a) (h a)
Można również zdefiniować nowy COMBINATOR jeśli chcesz być w stanie łańcucha nich łatwo i/lub nie chcą zadzierać z 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]
Oba przykłady pracy na GHC 7.6.3 nawet jeśli nie importować 'Control.Monad.Reader'. – sjakobi
Jestem 'liftM2' może (obecnie) być zastąpiony w następujący sposób:' filtr ((&&) <$> nieparzysty <*> (> 100)) [1.200] '. Co jest takie samo, ale ładniejsze. :) Wymaga również tylko 'Control.Applicative', i nie ma pełnych monad. ... Chociaż wciąż zastanawiam się, który operator zezwala na ANDing więcej niż dwie funkcje Boolean ... – Evi1M4chine