我正在使用的语言是Haskell的一个子集,名为Core Haskell,它不允许使用Haskell的内置函数。例如,如果我要创建一个函数来计算项x出现在列表xs中的次数,那么我会写:
count = \x ->
\xs -> if null xs
then 0
else if x == head xs
then 1 + count x(tail xs)
else count x(tail xs)
我正在尝试创建一个输出列表xs并删除其重复值的函数。例如。 remdups(7:7:7:4:5:7:4:4:[])=> (7:4:5:[])
任何人都可以提供任何建议吗?
谢谢!
答案 0 :(得分:2)
我猜你是学生,这是一个家庭作业问题,所以我会给你一部分答案并让你完成它。为了编写remdups
,有一个函数可以告诉我们列表是否包含元素。我们可以使用递归来做到这一点。使用递归时,首先要问自己“基本情况”是什么,或者最简单的情况。好吧,当列表为空时,显然答案是False
(无论字符是什么)。那么现在,如果列表不为空怎么办?我们可以检查列表中的第一个字符是否匹配。如果是,那么我们知道答案是True
。否则,我们需要检查列表的其余部分 - 我们通过再次调用该函数来完成。
elem _ [] = False
elem x (y:ys) = if x==y
then True
else elem x ys
下划线(_
)只是意味着“我不打算使用这个变量,所以我甚至都懒得给它命名。”这可以写得更简洁:
elem _ [] = False
elem x (y:ys) = x==y || elem x ys
写remdups
有点棘手,但我怀疑你的老师给了你一些提示。接近它的一种方法是想象我们处理列表的过程中途。我们有一部分尚未处理的列表,以及已处理的列表的一部分(并且不包含任何重复项)。假设我们有一个名为remdupHelper
的函数,它接受这两个参数,称为remaining
和finished
。它将查看remaining
中的第一个字符,并根据该字符是否在finished
中返回不同的结果。 (该结果可以递归调用remdupHelper
)。你能写remdupHelper
吗?
remdupHelper = ???
获得remdupHelper
后,您就可以编写remdups
了。它只是在初始条件下调用remdupHelper
,其中尚未处理任何列表:
remdups l = remdupHelper l [] -- '
答案 1 :(得分:1)
这适用于Ints:
removeDuplicates :: [Int] -> [Int]
removeDuplicates = foldr insertIfNotMember []
where
insertIfNotMember item list = if (notMember item list)
then item : list
else list
notMember :: Int -> [Int] -> Bool
notMember item [] = True
notMember item (x:xs)
| item == x = False
| otherwise = notMember item xs
它的工作原理应该是显而易见的。唯一“棘手”的部分是折叠器的类型是:
(a -> b -> b) -> b -> [a] -> b
但在这种情况下,b与[a]结合,因此它变为:
(a -> [a] -> [a]) -> [a] -> [a] -> [a]
因此,您可以传递insertIfNotMember函数,该函数的类型为:
Int -> [Int] -> [Int] -- a unifies with Int