如何删除嵌套列表中的重复项?

时间:2018-02-11 21:05:27

标签: list haskell functional-programming

我有一个名为flatten的Haskel函数,它可以这样工作:

flatten :: [[a]] -> [a] 
flatten []            = []
flatten ([]:vs)       = flatten vs
flatten ((x:xs):vs)   = x:flatten (xs:vs)

它需要一个列表列表并将其合并到一个列表中。如何创建另一个名为flatten2set的函数,它的工作方式与flatten(或调用flatten)完全相同,但是如果有的话,会删除所有重复项?我想尝试不用像nub这样的工具来做这件事。

一个例子是:

flatten2set [[1],[5,1,4],[9,1,3],[2,5]] --> [1,5,4,9,3,2]

我试图实现一个nub函数:

nub:: Eq a => [a] -> [a]
nub (x:xs) = x : filter (/=x) (myNub xs)
nub [] = []

当我试图像这样使用它时:

flatten2set :: [[a]] -> [a]
flatten2set[x] = (myNub . flatten) [x]

我收到此错误:

testing.hs:20:18:错误:

• No instance for (Eq a) arising from a use of ‘myNub’
  Possible fix:
    add (Eq a) to the context of
      the type signature for:
        flatten2set :: forall a. [[a]] -> [a]
• In the first argument of ‘(.)’, namely ‘myNub’
  In the expression: myNub . flatten
  In the expression: (myNub . flatten) [x]

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:3)

您有myNub

的出色表现
myNub :: Eq a => [a] -> [a]
myNub (x:xs) = x : filter (/=x) (myNub xs)
myNub [] = []

然后你试着把它叫做

flatten2set :: [[a]] -> [a]
flatten2set = myNub . flatten

但您已宣布flatten2set适用于任何 a。编译器只是指出那不可能。如果我们尝试使用功能列表列表调用flatten2set该怎么办?它不起作用,因为myNub需要Eq且功能无法比较。由于我们调用的函数需要Eq a,因此我们也必须要求Eq a

flatten2set :: Eq a => [[a]] -> [a]
flatten2set = myNub . flatten

我冒昧地删除了没有任何目的的[x]。如果你真的想要一个参数,你只需要命名参数。没有必要对其进行模式匹配。

flatten2set :: Eq a => [[a]] -> [a]
flatten2set x = (myNub . flatten) x

使用[x]是一个断言,在这种情况下,列表将只包含一个元素,我们希望flatten2set能够处理包含任意数量元素的列表。