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

Dam*_*ell 13 haskell list 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]
Run Code Online (Sandbox Code Playgroud)

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

我想懒惰地创建一个重复的整数列表,这样我们就可以简单地比较i和n的值.

repeatInts :: Int -> [Int]
Run Code Online (Sandbox Code Playgroud)

这样调用无限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]
Run Code Online (Sandbox Code Playgroud)

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

Gre*_*con 20

用途cycle:

cycle :: [a] -> [a]  
Run Code Online (Sandbox Code Playgroud)

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]
Run Code Online (Sandbox Code Playgroud)

对于好奇,GHC实现cycle

cycle [] = errorEmptyList "cycle"
cycle xs = xs' where xs' = xs ++ xs'
Run Code Online (Sandbox Code Playgroud)

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

详情见