如何在Haskell中合并有限数量的无限列表?

时间:2014-10-01 20:24:47

标签: list haskell functional-programming

对于赋值,我需要编写一些Haskell代码,其中包含由无限整数列表组成的有限列表作为输入,每个列表单调递增。

现在,我需要将这些合并到一个命令整数的列表中。此外,某些整数可能出现在多个列表中:在输出列表中,每个整数可能只在列表中出现一次。

所以如果输入是例如[[1,2,6,10,28,40 ......] [3,4,10,28,100,...],[任意数量的列表] ]那么输出应该是[1,2,3,4,6,10,28,40,100 ......]

我有点卡在这里。我不知道如何有效地使用foldr来合并列表。我想我应该比较每个列表的头部并从中列出一个新列表。

2 个答案:

答案 0 :(得分:7)

您可以通过考虑合并两个无限排序列表来简化问题,然后尝试进行概括。该合并的框架将如下所示:

mergeSorted :: Ord a => [a] -> [a] -> [a]
mergeSorted [] ys = ys
mergeSorted xs [] = xs
mergeSorted (x:xs) (y:ys) = ???

你必须比较x和y,并做一些明智的事情,可能涉及对mergeSorted的递归调用:这看起来不太糟糕,对吧?

现在,让我们假设mergeSorted有效,您可以将两个无限排序列表转换为一个无限排序列表。如何将N个无限排序列表转换为单个排序列表?为什么,这是一个简单的折叠!只需将两个列表合并在一起,然后将第三个列表与该列表合并,然后将第四个合并到该列表中,依此类推。

mergeAll :: Ord a => [[a]] -> [a]
mergeAll xss = foldr ???

答案 1 :(得分:1)

我们可以通过unfoldr pull({{1}重复从其中一个列表中拉出一个最小元素,合并任意一对无限单调增加列表(例如你有) }}在unfoldr)中,带

Data.List

我们可以成对处理任何有限列表,将其长度减半:

pull (x:xs,y:ys) | x<y = Just (x, (xs,y:ys))
                 | x>y = Just (y, (x:xs,ys))
                 | x==y = Just (x, (xs, ys))  -- pull same from both (NB!)

要重复一个步骤,直到满足条件,pairs f (x:y:t) = f (x,y) : pairs f t pairs _ t = t

的工作
until

不要忘记处理空列表案例。