Haskell 实现一个带折叠功能的过滤列表

Haskell implement a filter list with fold function

filterList :: (Eq a) => a -> [(a, b)] -> [(a, b)] 

>filterList " foo " [( " foo " , 1) , ( " bar " ,2) , ( " foo " ,3)]
[( " foo " ,1) ,( " foo " ,3)]

我想出了两种方法来解决这个问题,

`first way with list comprehension :` filterList a ((x,y):xs) =[(b,c)|(b,c)<-((x,y):xs),a==b]



  second way with recursive function: 
 filterList2 a []=[]
 filterList2 a ((x,y):xs)|a==x = (x,y):filterList2 a xs
                         |otherwise = filterList2 a xs

但是我想用文件夹功能解决,卡住了

filterList a ((x,y):xs) = foldr filter1 a ((x,y):xs)
                          
filter1 b ((x,y):xs)|b==x = (x,y)
                    |otherwise = filter1 b xs

这是行不通的。

非常感谢您的一点帮助。

filterListfilter1 函数都有问题。 filterList 函数具有如下模式:

filterList a <b>((x, y): xs)</b> = …

但这没有多大意义,类型签名和类型推断将保证它是一个二元组列表。您在此处的模式不适用于空列表,但可能仍然需要过滤空列表。因此,您应该将其简化为:

filterList a ls = …

foldr :: (a -> b -> b) -> b -> [a] -> b函数被赋予三个参数:

  • 折叠函数
  • 折叠空列表时使用的“base-case”;和
  • 元素列表。

但是您不能使用 a 作为基本情况,因为该基本情况还决定了结果的类型。这里的基本情况是空列表。我们还需要将 a 传递给 filter1 函数,因此我们可以将其实现为:

filterList :: Eq a => a -> [(a, b)] -> [(a, b)]
filterList a ls = foldr (filter1 <b>a</b>) [] ls

您的 filter1 函数适用于列表,但那不是 foldr 函数的工作方式。您传递给 foldr 的函数将被赋予一个元素,以及折叠列表其余部分的 结果 。因此你的函数看起来像:

filter1 :: Eq a => a -> (a, b) -> [(a, b)] -> [(a, b)]
filter1 a (x, y) rs = …

这里a是我们要找的已经传过去的元素,(x, y)是我们“折进去”的二元组,rs是结果折叠列表的其余部分。所以这是一个已经过滤的列表。

我将实施 filter1 作为练习。