I know one can do:
any (>3) [1,2,3,4,5]
but what is the elegant way of implementing:
any and[(>3),(<5)] [1,2,3,4,5]
or
all or[(<2),(>4)] [1,2,3,4,5]
etc?
I believe you'd like to check whether there are any elements that are both (<5)
and (>3)
.
You can do that this way:
any (\x -> x > 3 && x < 5) [1..5]
and your the other one can be done by
any (\x -> x < 2 || x > 4) [1..5]
But maybe it would be more fun to define &&
and ||
to work on functions:
infixr 3 &&&
infixr 3 |||
(&&&) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(f &&& g) x = f x && g x
(|||) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
(f ||| g) x = f x || g x
so now we can rewrite your examples as:
any ((>3) &&& (<5)) [1..5]
any ((<2) ||| (>4)) [1..5]
Your notation and[(>3),(<5)]
can be almost directly implemented as a higher order function. I'll call it andP
, since any
takes a predicate and a list of values, and we want a function that takes a list of predicates.
andP :: [a -> Bool] -> a -> Bool
andP ps x = all ($ x) ps
Now
andP [(>3), (<5)] x = x > 3 && x < 5
and you can write as in your initial request as
any (andP [(>3), (<5)]) [1,2,3,4,5]
As a side note, for this particular example, I think a clearer way would be:
between :: (Ord a) => a -> a -> a -> Bool
between lo hi x = lo < x && x < hi
any (between 3 5) [1,2,3,4,5]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With