List 列出唯一值

List 列出唯一值,list,haskell,recursion,list-comprehension,List,Haskell,Recursion,List Comprehension,我想知道如何使用Haskell列表理解从列表中获取唯一值。因此,如果我进入[2,4,5,4,4,6,2],它将返回[2,4,5,6] 最初,我从unique(y:ys)=[x | x开始@amalloy的评论,即列表理解仅限于“本地”视角,这是这里的关键见解。有一种明智的方法可以将nub作为列表理解来编写,但您首先需要改变您的视角 遗憾的是,库中省略了一个常用的函数,它用上下文装饰列表中的每个元素 picks :: [x] -> [([x], x, [x])] picks []

我想知道如何使用Haskell列表理解从列表中获取唯一值。因此,如果我进入[2,4,5,4,4,6,2],它将返回[2,4,5,6]


最初,我从unique(y:ys)=[x | x开始@amalloy的评论,即列表理解仅限于“本地”视角,这是这里的关键见解。有一种明智的方法可以将
nub
作为列表理解来编写,但您首先需要改变您的视角

遗憾的是,库中省略了一个常用的函数,它用上下文装饰列表中的每个元素

picks :: [x] -> [([x], x, [x])]
picks []       = []
picks (x : xs) = ([], x, xs) : [(x : bs, y, as) | (bs, y, as) <- picks xs]

列表中的每个元素放在三元组的中间,元素“之前”向左,元素“后”向右。

解释了深层结构,从某种意义上说,
picks
是一个“标准”操作,可以从列表结构派生出来。但我们不需要这些背景信息来部署它

picks
函数为我们提供了编写
nub
作为列表理解所需的上下文信息。我们所需要做的就是挑选出在它们自己的“before list”中没有出现的元素

myNub :: Eq x => [x] -> [x]
myNub xs = [x | (bs, x, as) <- picks xs, not (elem x bs)]
myNub::Eq x=>[x]->[x]
mynubxs=[x |(bs,x,as)你可以用一种(也许是不必要的聪明)懒惰的方式,从一点循环推理开始:输入的每个元素都应该出现在输出中,只有当它没有出现在输出中时

也就是说,对于像
[0,0,1]
这样的输入列表,应添加第一个
0
,但不应添加第二个
0

很明显,像这样的事情是行不通的:

unique xs = us
  where us = [x | x <- xs, x `notElem` us]
unique xs=us

其中us=[x | x不使用列表理解,只使用。或者,可能更好,根据您的使用情况,使用a而不是列表。是的,但我正在尝试在没有内置函数的情况下练习和解决它。在列表理解中仅使用保护子句是不可能的。这些限制在“局部”透视图,一次只查看一个元素。要基于输入的其余部分排除元素,您需要一些其他构造,例如
nub
或折叠。如果您想避免库函数,您必须以某种形式重新实现它们。首先定义一个函数,该函数给定
x
,并且
ys
删除所有e列表中出现的
x
ys
。然后使用递归扫描列表并删除重复项。这相当于您自己重写
nub
unique xs = us
  where us = [x | x <- xs, x `notElem` us]
unique xs = catMaybes us
  where
    us =
      [ if Just x `elem` take i us  -- If the element has appeared before here
        then Nothing                -- then don’t include it again
        else Just x                 -- otherwise do include it.
      | (i, x) <- zip [0..] xs      -- (Zip the elements with their indices.)
      ]