El liftM2 combinador puede ser utilizado en la mónada lector a hacer esto de una manera 'más funcional':
import Control.Monad
import Control.Monad.Reader
-- ....
filter (liftM2 (&&) odd (> 100)) [1..200]
Tenga en cuenta que las importaciones son importantes; Control.Monad.Reader proporciona la instancia de Monad (e ->) que hace que todo esto funcione.
El motivo por el que esto funciona es que la mónada del lector es justa (e ->) para algún entorno e. Por lo tanto, un predicado booleano es una función monádica 0-ary que devuelve bool en un entorno correspondiente a su argumento. Podemos usar liftM2 para distribuir el entorno sobre dos predicados.
O, en términos más simples, liftM2 actuará un poco como esto cuando los tipos funcionan:
liftM2 f g h a = f (g a) (h a)
También puede definir un nuevo combinador si desea ser capaz de cadena de éstos con facilidad, y/o no quieren meterse con 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]
Ambos ejemplos trabajan en GHC 7.6.3, incluso si no importar 'Control.Monad.Reader'. – sjakobi
Soy 'liftM2' puede (hoy en día) ser reemplazado así:' filter ((&&) <$> odd <*> (> 100)) [1.200] '. Lo cual es lo mismo, pero más bonito. :) También solo requiere 'Control.Applicative', y no hay mónadas completas. ... Aunque todavía me pregunto qué operador permite ANDing más de dos funciones booleanas ... – Evi1M4chine