在Haskell中结合多种过滤功能的绝佳方法 [英] Elegant way to combine multiple filtering functions in Haskell

查看:72
本文介绍了在Haskell中结合多种过滤功能的绝佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将以下过滤功能用作一元谓词,

 f1 :: Int -> Bool
f1 x = x > 30

f2 :: Int -> Bool
f2 x = x < 60

f3 :: Int -> Bool
f3 x = x `mod` 3 == 0
 

我想过滤所有整数列表.目前,我正在按照以下方式进行操作:

 filtered = filter f1 $ filter f2 $ filter f3 [1..90]
-- [33,36,39,42,45,48,51,54,57]
 

,但几乎没有感觉到这是最优雅的解决方案.特别是我不喜欢filter的多次重复以及缺乏可组合性.

是否有一种方法可以将所有这些谓词组合为一个,我们将其命名为<?>,以便可能的语法类似于以下内容?

 filtered = filter (f1 <?> f2 <?> f3) [1..90]
-- [33,36,39,42,45,48,51,54,57]
 

此假设的<?>运算符的类型签名将为(a -> Bool) -> (a -> Bool) -> (a -> Bool),但解决方案

这怎么办?

 import Control.Applicative (liftA2)
-- given f1 etc.
filtered = filter (f1 <&&> f2 <&&> f3) [1..90]
  where
    (<&&>) = liftA2 (&&)
 

在这里,将&&提升为Applicative会得到您标记为<?>的内容,即将两个一元谓词的结果组合在一起的运算符. /p>

(我最初将名称.&&.用作提升后的运算符,但 amalloy 建议<&&>将与其他Functor/Applicative提升的运算符(如<$> )类似,成为更好的名称​​.)

Given the following filtering functions as unary predicates,

f1 :: Int -> Bool
f1 x = x > 30

f2 :: Int -> Bool
f2 x = x < 60

f3 :: Int -> Bool
f3 x = x `mod` 3 == 0

I'd like to filter a list of integers through all of them. Currently I'm doing something along the lines of:

filtered = filter f1 $ filter f2 $ filter f3 [1..90]
-- [33,36,39,42,45,48,51,54,57]

but it hardly feels like this is the most elegant solution possible; especially I don't like the multiple repetitions of filter and the lack of composability.

Would there be a way to compose all these predicates into one, let's name it <?>, so that a possible syntax would resemble something like the following?

filtered = filter (f1 <?> f2 <?> f3) [1..90]
-- [33,36,39,42,45,48,51,54,57]

The type signature of this hypothetical <?> operator would then be (a -> Bool) -> (a -> Bool) -> (a -> Bool) but I wasn't able to find any such thing on Hoogle.

解决方案

What about this?

import Control.Applicative (liftA2)
-- given f1 etc.
filtered = filter (f1 <&&> f2 <&&> f3) [1..90]
  where
    (<&&>) = liftA2 (&&)

Here, lifting && to Applicative gives what you marked as <?>, i.e. an operator to and together the results of two unary predicates.

(I initially used the name .&&. for the lifted operator, but amalloy, suggested that <&&> would be a better name by analogy with the other Functor/Applicative lifted operators like <$>.)

这篇关于在Haskell中结合多种过滤功能的绝佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆