Haskell使用折叠功能实现过滤器列表

问题描述

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

>filterList " foo " [( " foo ",1),( " bar ",2),( " foo ",3)]
[( " 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 ((x,y): xs) = …

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

filterList a ls = …

foldr :: (a -> b -> b) -> b -> [a] -> b函数具有三个参数:

  • 折叠功能
  • “基本情况”,用于折叠空白列表;和
  • 元素列表。

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

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

您的filter1函数在列表上起作用,但是foldr函数却不是这样。您传递给foldr的函数将被赋予一个元素,并且 result 会折叠列表的其余部分。因此,您的函数如下所示:

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

这里a是我们必须通过的元素,(x,y)是我们要“折叠”的2元组,而rs是折叠其余列表。因此,这是一个已过滤的列表。

我将实施filter1作为练习。