在Haskell中过滤

时间:2014-10-21 19:36:39

标签: list haskell recursion filter tuples

我想要做的是接受元组列表,然后检查任何元组中的任何元素是否与int匹配。如果int匹配元组中的任一元素,则将元组添加到要返回的列表中。 一旦列表扫描了所有元组,它将返回一个仅与int匹配的元组列表。

filter1 :: (a -> Bool) -> [(Int, Int)] -> [(Int, Int)]  
filter1 _ [] = []  
filter1 p (x:xs)   
    | p x       = x : filter1 p xs  
    | otherwise = filter1 p xs

这是我到目前为止所拥有的。唯一的问题是它重新诅咒我得到一个错误因为我正在获取一个元组列表并将它放回一个应该只是一个int的地方。

2 个答案:

答案 0 :(得分:4)

如果你不介意的话,我会给你GHCI的一些控制台输出。

filter的类型签名是:

Prelude> :t filter
filter :: (a -> Bool) -> [a] -> [a]

换句话说,filter是一个带有两个参数的函数:第一个是从任何类型a到类型Bool的函数,第二个是a元素的列表。然后,它会为您提供a个元素的列表(函数发回的元素True)。

您尝试filter1 (5, 6) [(5, 6), (7, 8)]的示例代码几乎正确,应改为:

Prelude> filter (\x -> x == (5, 6)) [(5, 6), (7, 8)]
[(5, 6)]

我们可以使用Haskell为运算符提供的特殊语法来编写谓词。对于任何操作员,请将其称为*+以获取此解释。然后(*+)\x y -> x *+ y相同,(a *+)\y -> (a *+ y)相同,(*+ b)\x -> x *+ b相同。因此,我们可以将上述过滤条件简单地编写为((5,6) ==),我们可以通过定义来使您的示例代码工作:

Prelude> let filter1 val = filter (val ==)
Prelude> :t filter1
filter1 :: Eq a => a -> [a] -> [a]
Prelude> filter1 (5, 6) [(5, 6), (7, 8)]
[(5,6)]

然而这不是你问的。你问的是接受一个元组列表,然后检查任何元组中的任何元素是否与int 匹配。要做到这一点,我们也需要接受int:

Prelude> let tfilter n = filter (\(a, b) -> a == n || b == n)
Prelude> :t tfilter
tfilter :: Eq a => a -> [(a, a)] -> [(a, a)]
Prelude> tfilter 3 [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
[(2,3),(3,4)]

答案 1 :(得分:0)

箭头方式:

filter :: ( a -> Bool ) -> [ (Int, Int) ] -> [ (Int, Int) ]

生成过滤谓词( (Int, Int) -> Bool )

&&&可用于提供( Int -> Bool, Int -> Bool )

例如,

( (==) &&& (==) ) 3将产生( (==3), (==3) )

这两个部分可以通过解除它来传递给***

( uncurry (***) ) ( (==3), (==3) )将产生( (==3) *** (==3) )

生成的箭头可用于测试我们的元组值

( (==3) *** (==3) ) (4,3)将产生(False, True)

然后,通过uncurrying (||),我们得到一个函数,它接受一个布尔元组并给出它的逻辑或。

( uncurry (||) ) (False, True)将产生True

现在我们最终得到了这个:

f n tup = uncurry (||) $ ( uncurry (***) . ((==) &&& (==)) ) n tup

uncurry (||)的构图延迟到其余时间 部分( uncurry (***) . ((==) &&& (==)) )已应用于ntup

f = (uncurry (||) .) . uncurry (***) . ((==) &&& (==))

多数民众赞成。

f 3 (4,5) => False

f 3 (4,3) => True

现在我们可以使用带有过滤器的f谓词来获得所需的结果。

tfilter = filter . f

tfilter = filter . (uncurry (||) .) . uncurry (***) . ((==) &&& (==))

tfilter 3 [ (x,y) | x<-[3..6], y<-[1..4] ]

=&GT; [(3,1),(3,2),(3,3),(3,4),(4,3),(5,3),(6,3)]