因此,如果我想构建一个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 = []
答案 0 :(得分:8)
我绝对会选择第二种,因为它显然有效且足够清晰。第一个将取决于genericReplicate
是否能够以某种方式融合++
。找出肯定的最佳方法是运行
ghc -O2 -ddump-simpl -dsuppress-all whatever.hs | less
并对其喷出的东西进行了研究。
也就是说,一个循环的整个长度实际上将分配在内存中。这就是目前实施的循环功能的性质,并且似乎不太可能改变(除非一些显着的前进 - 折叠/构建融合似乎不够)。因此,通过以不同方式编写其余代码,您可能最好完全避免这种情况。
怪异n = genericReplicate n 0 ++ [1] ++ weirdthing n
这是我的最终答案。这会产生无限列表而不是循环列表,但当n
足够大时, 。