在Haskell中结合多种过滤功能的绝佳方法 [英] Elegant way to combine multiple filtering functions in 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屋!