我尝试连接两个列表,使得结果列表中的元素只出现一次。 我不想使用预定义的功能,因为那样太容易了。因为我正在学习haskell,我写下面的代码:
import Data.List
add :: [Int] -> [Int] -> [Int]
add xs ys = zs ++ ws
where
zs = if elem x (x:xs) == True then x:(elem x xs)
else elem x xs
ws = if elem y (y:ys) == True then y:(elem y ys)
else elem y ys
我只使用预定义的函数elem,它告诉我元素是否出现在列表中。 我的想法是首先列出一个列表并使用" elem"找出列表xs的第一个元素x是否多次存在于列表中。如果是这样,那么我接受x并使用":#34; -operator和(elem x xs)我建立一个新列表,直到检查完所有元素。 我对第二个列表做了同样的事情。 如果完成,那么我使用" ++" - 运算符用zs ++ ws连接无副本列表。所以当我编译它时,ghci告诉我x和y不在范围内。我的错误在哪里?
答案 0 :(得分:7)
您还没有给出此功能的预期输入/输出示例,因此我将使用您提供的定义 -
"连接两个列表,使得结果列表中的元素只出现一次。"
似乎有一种直截了当的方法 -
因此,让我们假设您有一个函数unique :: [Int] -> [Int]
,可以从列表中删除重复项(同时保持元素的顺序)。那么你想要的就像
add :: [Int] -> [Int] -> [Int]
add xs ys = unique (xs ++ ys)
因此,您已将问题简化为编写unique
函数的简单问题。你能做到吗?
答案 1 :(得分:4)
我认为克里斯的解决方案是可行的方法。但是为了教学,我将讨论你的方法中的一些问题。首先,为了在函数x
中引用y
和add
,必须在某处定义它们。我怀疑你的意图是什么:
add (x:xs) (y:ys) = ...
现在,您可以在函数定义中使用x
,xs
,y
和ys
。现在任何时候你都想写下这样的东西:
if condition == True then...
知道写
更简单,更清晰if condition then...
所以我认为你打算写一些这样的东西:
add (x:xs) (y:ys) = zs ++ ws
where
zs = if elem x xs then xs
else x:xs
ws = if elem y ys then ys
else y:ys
除了您还想进行某种递归以确保xs
或ys
中的所有元素都不重复。然而,递归两个列表将是非常尴尬和困难的。这就是为什么克里斯的答案更好,以及更接近Haskell-y方式的原因。
另请注意,而不是
elem x xs
写起来可以更具可读性
x `elem` xs