为什么在Haskell中删除重复的函数有两个参数而不是一个?

时间:2017-02-27 15:45:06

标签: list haskell duplicates

帮助我理解为什么函数removeDuplicates只有一个参数,但它下面的函数rdHelper有两个?它有效,并且在列表中尝试它没有错误。

removeDuplicates :: Eq a => [a] -> [a] 
removeDuplicates = rdHelper []     
    where rdHelper seen [] = seen  
          rdHelper seen (x:xs)
              | x `elem` seen = rdHelper seen xs 
              | otherwise = rdHelper (seen ++ [x]) xs

也许它与状态变量相关联?但我不确定它是什么

2 个答案:

答案 0 :(得分:4)

为了删除重复项,您需要以某种方式存储您已经看到的。这就是变量被称为seen的原因。最初在递归中,您还没有看到任何元素,因此seen为空。

每次发出值时,都会将其添加到累加器seen。比如说你打电话给removeDuplicates [1,2,3,1,4,2]。然后它将被评估为:

removeDuplicates [1,2,3,1,4,2]
    rdHelper [] [1,2,3,1,4,2]
        (1 : rdHelper [1] [2,3,1,4,2])

所以现在rdHelper会被调用,我们知道1已经发出,所以我们应该将其过滤掉。接下来我们执行:

removeDuplicates [1,2,3,1,4,2]
    rdHelper [] [1,2,3,1,4,2]
        (1 : rdHelper [1] [2,3,1,4,2])
            (1 : 2 : rdHelper [1,2] [3,1,4,2])
                (1 : 2 : 3 : rdHelper [1,2,3] [1,4,2])

所以现在我们在1位于第二个列表的头部,但因为它也是elem的{​​{1}},我们将忽略该元素。

您的代码中存在错误,因为seen永远不会发出错误。另外请注意,您可以通过添加到头部来提高性能(添加到头部不会改变程序的语义,但会使其运行得更快):

rdHelper

答案 1 :(得分:1)

Sub MyMacro() Workbooks.Open Filename:="C:\Zeszyt1.xlsx" Columns("A:A").ColumnWidth = 100 ActiveWorkbook.Save ActiveWindow.Close End Sub 是一个辅助函数,它累积了所看到的元素的列表,以及原始列表中剩余的元素列表。因为Haskell中没有变异,所以两个累加器列表都作为参数传递给辅助函数,并且它以递归方式调用自身。