我有一个名为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]
任何帮助将不胜感激!
答案 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
能够处理包含任意数量元素的列表。