如何组合过滤条件

24 haskell filter

过滤器类函数采用条件(a - > Bool)并在过滤时应用它.

当您有多个条件时,使用过滤器的最佳方法是什么?

使用应用函数liftA2而不是liftM2,因为我出于某种原因不明白liftM2如何在纯代码中工作.

bdo*_*lan 31

liftM2组合器可以在Reader monad中以"更多功能"的方式使用:

import Control.Monad
import Control.Monad.Reader

-- ....

filter (liftM2 (&&) odd (> 100)) [1..200]
Run Code Online (Sandbox Code Playgroud)

请注意,进口很重要; Control.Monad.Reader提供Monad(e - >)实例,使其全部工作.

这个工作的原因是读者monad只是(e - >)对于某些环境e.因此,布尔谓词是0-ary monadic函数,在与其参数对应的环境中返回bool.然后我们可以使用liftM2将环境分布在两个这样的谓词上.

或者,简单来说,当类型解决时,liftM2会有点像这样:

liftM2 f g h a = f (g a) (h a)
Run Code Online (Sandbox Code Playgroud)

如果您希望能够轻松地链接这些组合器,并且/或者不想弄乱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]
Run Code Online (Sandbox Code Playgroud)

  • 即使您不导入`Control.Monad.Reader`,这两个示例都适用于GHC 7.6.3. (4认同)
  • 我是'liftM2`可以(现在)被替换为:`filter((&&)<$> odd <*>(> 100))[1.200]`.哪个是相同的,但更漂亮.:)它也只需要`Control.Applicative`,而不是完整的monad....虽然我仍然想知道哪个运算符允许ANDing超过两个布尔函数... (4认同)

Jon*_*nas 16

好吧,你可以在Haskell中组合你想要的函数(只要类型是正确的)并使用lambdas你甚至不必命名你的谓词函数,即,

filter (\x -> odd x && x > 100) [1..200]
Run Code Online (Sandbox Code Playgroud)


Aym*_*ieh 11

假设您的条件存储在名为的列表中conditions.此列表具有类型[a -> Bool].

要将所有条件应用于值x,您可以使用map:

map ($ x) conditions
Run Code Online (Sandbox Code Playgroud)

这将每个条件应用于x并返回Bool列表.要将此列表减少为单个布尔值,如果所有元素都为True,则为True,否则为False,则可以使用以下and函数:

and $ map ($ x) conditions
Run Code Online (Sandbox Code Playgroud)

现在你有一个结合所有条件的功能.我们给它一个名字:

combined_condition x = and $ map ($ x) conditions
Run Code Online (Sandbox Code Playgroud)

这个函数有类型a -> Bool,所以我们可以在调用时使用它filter:

filter combined_condition [1..10]
Run Code Online (Sandbox Code Playgroud)

  • 你已经发现了`all`函数:`filter(所有条件)[1..10]` (10认同)
  • @Peter:都有类型(a - > Bool) - > [a] - > Bool,而不是[(a - > Bool)] - > a - > Bool. (4认同)
  • 小心($ x)而不是($ x),好像你因为其他原因打开了模板Haskell,$ x会突然看起来像拼接. (2认同)
  • 仍然,而不是`和$ map($ x)条件`可以输入:`all($ x)conditions` (2认同)