代码之家  ›  专栏  ›  技术社区  ›  Damian Powell

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

  •  12
  • Damian Powell  · 技术社区  · 15 年前

    我是一个试图从埃里克·梅耶尔的第九频道网络广播中自学哈斯克尔的人。我遇到了一个有趣的难题,它涉及到使用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 回复  |  直到 7 年前
        1
  •  19
  •   Greg Bacon    7 年前

    使用 cycle :

    cycle :: [a] -> [a]  
    

    周期 将一个有限列表绑定到一个圆形列表中,或者等价于原始列表的无限重复。它是无限列表上的标识。

    你可以定义 repeatInts 依据 周期 :

    *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 [] = errorEmptyList "cycle"
    cycle xs = xs' where xs' = xs ++ xs'
    

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

    有关详细信息,请参阅

        2
  •  2
  •   Sam R. chikka.anddev    11 年前

    回答迟了,但也可以这样写:

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