haskell, chaining filters
to write "map f (map g xs)" as a single call to map you could write
example xs = map (f.g) xs
but how would you write "filter p (filter q xs)" as a single call to filt开发者_StackOverflower? the dot operator doesnt seem to work for filter as it does for maps. guessing you'd use something else for predicates?
If you defined a function both
that looked like this:
both :: (a -> Bool) -> (a -> Bool) -> a -> Bool
both f g x = f x && g x
Then you could write:
example xs = filter (both p q) xs
I'm not sure if there's a standard function that does this for you...
$ ghci Prelude> :m +Control.Arrow Prelude Control.Arrow> :t uncurry (&&) . ((0 <) &&& (< 10)) uncurry (&&) . ((0 <) &&& (< 10)) :: (Num a, Ord a) => a -> Bool Prelude Control.Arrow> filter (uncurry (&&) . ((0 <) &&& (< 10))) [0..15] [1,2,3,4,5,6,7,8,9]
Or declare your own operators, if you'll be doing this often.
infixr 3 &&:
p &&: q = \a -> p a && q a
infixr 2 ||:
p ||: q = \a -> p a || q a
not' = (.) not
all' = foldr (&&:) $ const True
any' = foldr (||:) $ const False
example xs = filter (p &&: q ||: not' r) xs
Why not a list comprehension?
example = [x | x <- xs, p x, q x]
-- for example
example = [x | x <- [1..10], (>3) x, x<5 ] -- [4]
Calling a list of functions on something is essentially what the ap
function in Control.Monad does. Then you just and
the results. The only slight ugliness is that ap
requires both its arguments to be in the same monad (List in this case), so we need to compose it with return
to work here.
import Control.Monad
filterByMany funcs = filter (and . ap funcs . return)
I would define a lambda expression.
module Main where
overTen :: Int -> Bool
overTen = (>10)
main :: IO ()
main = do
print $ filter (\x -> overTen x && even x) [1..20]
output:
$ ghci Test.hs
GHCi, version 6.10.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( Test.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
[12,14,16,18,20]
*Main>
import Data.Foldable
import Data.Monoid
p = (>4)
g = (<10)
main = print $ filter (getAll . foldMap (All.) [p,g]) [1..10]
outputs
[5,6,7,8,9]
just because lists are foldable, and you can combine predicate results with the All
monoid
What about something like:
example xs = filter (forAll [p,q,r,s,t,u,v]) xs
forAll:: [(a -> Bool)] -> a -> Bool
forAll funcs x = all (map ($ x) funcs)
I'd define a helper function -- this could probably be written more declaratively, but I don't have GHCI installed on this system for testing:
allPredicates :: [a -> Bool] -> a -> Bool
allPredicates [] _ = True
allPredicates (p:ps) x = p x && allPredicates ps x
then
filter (allPredicates [p, q]) xs
精彩评论