【问题标题】:Construction of infinite list in HaskellHaskell中无限列表的构造
【发布时间】:2012-10-04 05:09:32
【问题描述】:

对于所需的无限列表,我有两件事:它的第一个元素

x :: A

以及生成下一个元素的函数

f :: [A] -> A

创建无限列表的最佳(最惯用的?最快的?)方法是什么?我是说

xs = x : f [x] : f [x, f [x]] : f [x, f [x], f [x, f [x]]] : ...

【问题讨论】:

  • 你在搜索unfoldr函数吗?
  • unfoldr 的类型为unfoldr :: (b -> Maybe (a, b)) -> b -> [a],所以您的意思是将“当前”整个列表返回为b,并将下一个元素返回为a?谢谢,这似乎真的有效=)
  • 但是有没有更直接的方法?
  • infiniteList = x:map f (tail $ inits infiniteList) 其中x 是第一个元素,f 是要应用于每个前缀的函数。
  • 您可以使用迭代:map head $ iterate (\l -> f l : l) [x]。注意l 是颠倒的(l 是前面元素的列表),所以可能是\l -> f (reverse l) : l

标签: haskell infinite-sequence


【解决方案1】:

你想要的功能可以实现为:

constructInf :: ([a] -> a) -> a -> [a]
constructInf f x = xs
  where xs = x:map f (tail $ inits xs)

consrtuctInf 的性能取决于它的参数函数f 的性能。假设 f 花费 O(N) 时间,那么 constructInf 将花费 O(M*N) 时间,其中 M 是您将检查的 constructInf 结果中的元素数。

【讨论】:

  • 那么内存使用情况呢? inits 不会创建许多子列表,这些子列表都在使用而不是 GC'ed?
  • 请注意:这种情况下的时间将是O(M^2),因为N1变为M
  • @hammar:谢谢,当当前代码太慢时,这一点值得记住。
  • @chersanya 用于内存使用,是的inits 将创建许多中间列表。但是,这些中间列表只会在需要时构建,并在使用后进行垃圾收集。我不确定列表融合是否可以在这里做任何事情。
【解决方案2】:

你想要iterate

take 10 $ iterate (+1) 0

= [0,1,2,3,4,5,6,7,8,9]

如果您目前需要整个列表,并且不介意将其反转,您可以这样做:

mkl f x0 = x0 : unfoldr (\xs -> let x = f xs in Just (x, x:xs)) [x0]

如果到目前为止你需要整个列表,并且你希望它按顺序排列,那将是非常低效的,但你可以这样做:

mkl' f x0 = x0 : unfoldr (\xs -> let x = f xs in Just (x, xs ++ [x])) [x0]

但我不确定为什么您需要整个列表而不是最后一个元素。

【讨论】:

  • 哦,你想要到目前为止的整个列表在每次迭代中? iterate 只是获取前一个元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 2012-10-22
相关资源
最近更新 更多