【问题标题】:Haskell, define an infinite list, add data on the fly and sort at the same time. How?Haskell,定义一个无限列表,同时添加数据和排序。如何?
【发布时间】:2012-03-30 06:19:40
【问题描述】:

我必须定义一个列表,其中:

  • 1 是会员
  • 如果 n 是一个成员,那么 2n+1 和 3n+1 也是

所以列表是无限的,必须排序。加载到 GHCi 时,命令:

"take 10 theList"

将产生:

[1,3,4,7,9,10,13,15,19,21]

以下是我的代码:

theList = ([1] ++ concat [[(x*2+1),(x*3+1)]|x<-theList])

它似乎工作,除了它没有排序,与上面相同的命令产生:

[1,3,4,7,10,9,13,15,22,21]

有没有人有办法解决这个问题? 谢谢

【问题讨论】:

  • 您的allInOne 函数正是concat。 Haskell 有许多“内置”功能,您可以使用 Hoogle 按类型签名进行搜索(它是让 Haskell 令人惊叹的工具之一!),例如allInOne 具有 [[a]] -&gt; [a] 类型,而 the first result 是您要查找的类型。 :)
  • 有一个很好的自然实现涉及 corecursion。在某种程度上,它类似于无限的斐波那契数列:fibs = 0:1:zipWith (+) fibs (tail fibs)。当您已经拥有一定大小的 theList 时,您将如何扩展列表?

标签: list haskell lazy-evaluation


【解决方案1】:

这个问题可以看作是一个无限二叉树(AB 是分支的标签):

  1__ B
  |  4___
  |   \  13 ...
A 3_   \
  | \   9 ...
  7  10
  ...

这样想,我们可以看到我们要编写一个函数(“listify”),将“树”转换为排序列表。这是 Haskell 真正好的地方:如果我们有一个函数 (merge),它接受两个(无限)排序列表并将它们合并到一个排序列表中(你应该编写这个函数),那么 listify-ing 树是只需listify-ing 两个分支,合并它们并将根放在开头,即在上面的树中

1:merge (listify A) (listify B)

由于这是作业我就不多说了,但是树的任何一个分支都是完全由根节点决定的,所以listify的类型签名可以是Integer -&gt; [Integer]。一旦你有listify,然后是theList = listify 1

【讨论】:

  • 谢谢。我刚刚尝试过,但由于列表未排序,因此无法合并或排序它们。如果它有效,我只需要在列表定义前面放置另一个 sort 函数。问题是,如果我这样做了,并且尝试了 take 20 theList Haskell 会崩溃(这意味着它没有返回到 Main&gt; 命令。我想我必须即时创建列表,并尽快对其进行排序随着新元素被放入其中。我能想到的唯一方法是: theList = [x|x
  • 如果您正确编写了listifymerge,则列表排序(我知道这不是很有帮助)。 Haskell 可能会崩溃,因为您正在创建一个无限循环(可能“listify n”出现在listify n 定义的右侧?或者在merge 中类似?)。
  • 这样做的问题是重复只在合并步骤处理,而不是在生成期间处理,随着时间的推移,这会导致大量不必要的工作。不过,它确实创建了一个非常简洁的声明性定义。
  • @dan_waterworth 不过,这并没有太多额外的工作:由于合并是递归生成的部分,因此几乎可以尽快过滤重复项。当然有更有效的方法,但除非你真的想要很多数字,否则应该没问题。即使在 ghci 中,我也能在一分钟内获得大约 5000000!
  • 我终于做到了,不知道我的想法是否和你的提示一样,但是代码看起来非常简单:aList = [1] ++ merge [2*x+1| x
【解决方案2】:

另一种看待它的方式是过滤整数列表。如果 n = 1 (mod 2) 并且 (n-1)/2 是序列的一部分,或者如果 n = 1 (mod 3) 并且 (n-1)/3 是序列的一部分,则数字 n 是序列的一部分序列的一部分。

【讨论】:

  • 感谢您的回答,但它不适用于整数,因为 (6 - 1) mod 3 = 1,但 6 不应该在列表中,如您在我的问题。这里有一个很大的舍入问题。
  • @crazyfffan,我认为这确实有效:6 /= 1 (mod 3),所以部门甚至都没有考虑过。 (moddiv是不同的功能)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-06
  • 2020-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
相关资源
最近更新 更多