如何在Haskell中创建无限重复列表?

时间:2010-01-09 23:48:25

标签: list haskell lazy-evaluation

我是一名C#人,试图从Erik Meijer的第9频道网络广播中自学Haskell。我遇到了一个有趣的谜题,其中包括使用zip和mod跳过列表中的每个'n'元素。

every :: Int -> [a] -> [a]
every _ [] = []
every n xs = [x | (x,i) <- zip xs [1..], i `mod` n == 0]

如果我们可以避免使用mod,我一直认为它可能更有效(对于非常大的列表或流)。

我考虑过懒惰地创建一个重复的整数列表,这样我们就可以简单地将i的值与n进行比较。

repeatInts :: Int -> [Int]

这样调用repeatInts 3无限回复[1,2,3,1,2,3,1,2,3,1,2,3,..]

鉴于此,我们可以像这样重新定义every

every :: Int -> [a] -> [a]
every _ [] = []
every n xs = [x | (x,i) <- zip xs (repeatInts n), i == n]

所以我的问题是:你将如何实施repeatInts

2 个答案:

答案 0 :(得分:20)

使用cycle

cycle :: [a] -> [a]  
     

cycle将有限列表绑定到循环列表中,或等效地,将原始列表无限重复。这是无限名单上的身份。

您可以使用repeatInts

来定义cycle
*Main> let repeatInts n = cycle [1..n]
*Main> :t repeatInts
repeatInts :: (Num t, Enum t) => t -> [t]
*Main> take 10 $ repeatInts 3
[1,2,3,1,2,3,1,2,3,1]

对于好奇,GHC使用

实现cycle
cycle [] = errorEmptyList "cycle"
cycle xs = xs' where xs' = xs ++ xs'

在纯粹的功能性说法中,这种奇怪的技术被称为<绑定结,它创建循环数据结构而不是无限数据结构。

详见

答案 1 :(得分:2)

迟到的答案,但它也可以这样写:

repeatInts :: Int -> [Int]
repeatInts 0 = []
repeatInts a = [1..a] ++ repeatInts a