我为删除列表中的常用元素创建了此代码,但它仅适用于整数列表我有一个示例
remove [ A "List", A "List", A "Gone", A "Still"]
它必须作为输出[ A "List", A "Gone", A "Still"]
它不起作用给出一个未定义的构造函数A
remove [] = []
remove (x:xs) | x `elem` xs = remove xs
| otherwise = x : remove xs
答案 0 :(得分:3)
这里的问题本身不是函数本身,而是输入列表:
remove [ A "List", A "List", A "Gone", A "Still"]
它包含一个元素列表,每个元素都有数据构造函数 A
后跟一个字符串。在像Prolog这样的语言中,可以动态引入仿函数,但不能在Haskell中引入:Haskell是静态类型的,因此您需要声明类型。例如,我们可以声明类型:
data A = A String deriving (Eq, Show)
现在我们声明了一个类型A
,其中有一个数据构造函数A
,它将String
作为参数。我们使它成为deriving (Eq, Show)
,这样两个A
是相等的,因为它们具有相同的数据构造函数(但由于只有一个,所以总是如此),以及参数应该是相同的。 Show
使我们能够打印A
个实例。
所以现在它至少会产生输出(不会产生编译器错误)。但是函数本身仍然存在一个潜在的问题:在这里检查列表中 tail 的成员资格。可能有两个问题:
remove [1, 4, 1, 2]
将返回[4, 1, 2]
,而我们可能希望返回[1, 4, 2]
;和elem
,将继续寻找重复。结果最终Haskell将耗尽内存并崩溃。我们最好在这里使用一个存储迄今为止观察到的元素的累加器,并在该列表上调用elem
,如:
remove :: Eq a => [a] -> [a]
remove = go []
where go _ [] = []
go seen (x:xs) | elem x seen = go seen xs
| otherwise = x : go (x:seen) xs