多个元素的布尔运算符

per*_*nto 3 haskell

我知道可以做到:

any (>3) [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

但优雅的实施方式是什么:

any and[(>3),(<5)] [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

要么

all or[(<2),(>4)] [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

等等?

And*_*ewC 10

我相信你想检查是否有任何元素(<5)(>3).

你可以这样做:

any (\x -> x > 3 && x < 5) [1..5]
Run Code Online (Sandbox Code Playgroud)

你的另一个可以完成

any (\x -> x < 2 || x > 4) [1..5]
Run Code Online (Sandbox Code Playgroud)

但也许定义&&||处理函数会更有趣:

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
Run Code Online (Sandbox Code Playgroud)

所以现在我们可以将你的例子重写为:

any ((>3) &&& (<5)) [1..5]
any ((<2) ||| (>4)) [1..5]
Run Code Online (Sandbox Code Playgroud)

  • 好吧,`( - >)a`是一个monad,但它通常是一个applicative functor,所以`liftA2`在这里可能更合适(或者只使用`(&&)<$>(> 3)<*>( <5)`直接). (9认同)

luq*_*qui 6

您的符号and[(>3),(<5)]几乎可以直接实现为高阶函数.我会称之为andP,因为any需要一个谓词和一个值列表,我们想要一个带有谓词列表的函数.

andP :: [a -> Bool] -> a -> Bool
andP ps x = all ($ x) ps
Run Code Online (Sandbox Code Playgroud)

现在

andP [(>3), (<5)] x = x > 3 && x < 5
Run Code Online (Sandbox Code Playgroud)

你可以像在初始请求中那样写

any (andP [(>3), (<5)]) [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

作为旁注,对于这个特定的例子,我认为更清晰的方式是:

between :: (Ord a) => a -> a -> a -> Bool
between lo hi x = lo < x && x < hi

any (between 3 5) [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)