在Haskell中构造循环列表的最便宜的方法

时间:2014-08-19 02:17:48

标签: haskell optimization lazy-evaluation circular-list

因此,如果我想构建一个n 0&1和1 1的循环列表,以下哪种方式更好/更便宜?还有更好/更便宜的方式吗?考虑到n是Integer并且可能很大(尽管实际上它不会超过2 ^ 32)。

aZerosAndOnes :: Integer -> [Int]
aZerosAndOnes n 
    | n >= 0    = cycle (genericReplicate n 0 ++ [1])
    | otherwise = []

bZerosAndOnes :: Integer -> [Int]
bZerosAndOnes n 
    | n >= 0    = tail (cycle (1 : genericReplicate n 0))
    | otherwise = []

1 个答案:

答案 0 :(得分:8)

我绝对会选择第二种,因为它显然有效且足够清晰。第一个将取决于genericReplicate是否能够以某种方式融合++。找出肯定的最佳方法是运行

ghc -O2 -ddump-simpl -dsuppress-all whatever.hs | less

并对其喷出的东西进行了研究。


也就是说,一个循环的整个长度实际上将分配在内存中。这就是目前实施的循环功能的性质,并且似乎不太可能改变(除非一些显着的前进 - 折叠/构建融合似乎不够)。因此,通过以不同方式编写其余代码,您可能最好完全避免这种情况。


是的,我想到了其他的东西。如果您在"单线程"中使用此列表时尚,你可以完全免除周期:

怪异n = genericReplicate n 0 ++ [1] ++ weirdthing n

这是我的最终答案。这会产生无限列表而不是循环列表,但当n足够大时,