Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 为什么Haskell中的remove duplicate函数有两个参数而不是一个?_List_Haskell_Duplicates - Fatal编程技术网

List 为什么Haskell中的remove duplicate函数有两个参数而不是一个?

List 为什么Haskell中的remove duplicate函数有两个参数而不是一个?,list,haskell,duplicates,List,Haskell,Duplicates,请帮助我理解为什么函数removeDuplicates只有一个参数,而它下面的函数rdHelper有两个参数?它可以工作,并且在列表中尝试时没有错误 removeDuplicates :: Eq a => [a] -> [a] removeDuplicates = rdHelper [] where rdHelper seen [] = seen rdHelper seen (x:xs) | x `elem` s

请帮助我理解为什么函数
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

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

rdHelper
是一个helper函数,它累加所看到的那些元素的列表,以及原始列表中剩余的元素列表。因为Haskell中没有突变,两个累加器列表都作为参数传递给helper函数,并且它递归地调用自己。

rdHelper
是一个helper函数,它累加所看到的那些元素的列表,以及原始列表中剩余的元素列表。由于Haskell中没有突变,两个累加器列表都作为参数传递给helper函数,并且它会递归调用自身。

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

但是,每次发出值时,都会将其添加到累加器
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
位于第二个列表的开头,但由于它也是一个
seen
元素,我们将忽略该元素

您的代码中有一个bug,因为
rdHelper
从不发出任何东西。此外,请注意,您可以通过添加到头部来提高性能(添加到头部不会改变程序的语义,但会使程序运行得更快):

removeDuplicates::Eq a=>[a]->[a]
RemovedUpplicates=rdHelper[]
其中rdHelper seen[]=seen
rdHelper(x:xs)
|x`elem`seen=rdHelper seen xs
|否则=x:rdHelper(x:seed)xs

--^emit element^add to head
为了删除重复项,您需要以某种方式存储您已经看到的值。这就是为什么变量被称为
seen
。最初在递归中,您没有看到任何元素,因此
seed
为空

但是,每次发出值时,都会将其添加到累加器
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
位于第二个列表的开头,但由于它也是一个
seen
元素,我们将忽略该元素

您的代码中有一个bug,因为
rdHelper
从不发出任何东西。此外,请注意,您可以通过添加到头部来提高性能(添加到头部不会改变程序的语义,但会使程序运行得更快):

removeDuplicates::Eq a=>[a]->[a]
RemovedUpplicates=rdHelper[]
其中rdHelper seen[]=seen
rdHelper(x:xs)
|x`elem`seen=rdHelper seen xs
|否则=x:rdHelper(x:seed)xs

--^emit element^ add to head
“因为Haskell中没有变异,两个累加器列表都作为参数传递给helper函数。”请详细说明一下。您在原始帖子中提到了“state variable”,因此我认为您有使用命令式语言的经验。Haskell中的术语“变量”没有多大意义,因为所有的值都是不可变的。没有可以更改的“状态”,函数只能根据作为参数传入的值返回值。“因为Haskell中没有变异,两个累加器列表都作为参数传入帮助器函数。”请详细说明一下。您在最初的帖子中提到了“状态变量”,所以我觉得你对命令式语言有经验。Haskell中的术语“变量”没有多大意义,因为所有的值都是不可变的。没有可以更改的“状态”,函数只能根据作为参数传入的值返回值。谢谢Willem,你的帖子解释了一切。谢谢Willem,你的帖子解释了一切。