【问题标题】:How to create infinitely repeating list in Haskell?如何在 Haskell 中创建无限重复列表?
【发布时间】:2011-01-03 08:58:31
【问题描述】:

我是一名 C# 人,试图通过 Erik Meijer 的 Channel 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

【问题讨论】:

标签: list haskell lazy-evaluation


【解决方案1】:

使用cycle:

cycle :: [a] -> [a]  

cycle 将一个有限列表绑定到一个循环列表中,或者等效地,将原始列表的无限重复联系起来。它是无限列表上的身份。

您可以根据cycle 定义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 实现了

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

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

详情见

【讨论】:

  • 谢谢,gbacon。不知怎的,我知道会有一个简单的答案!现在我可以深入了解cycle 的工作原理了。
  • 有点奇怪,cycle 是标准的 Haskell '98,尽管循环列表不是。看看源(上面)是怎么说的 - 你可能会或可能不会得到一个循环列表......
  • 有趣的是,这个 Q/A 本身就是 XY 问题的一个实例。 ;) 跳过列表中的每个第 n 个元素不应涉及任何 mod,也不应数到无穷大。正确的解决方案似乎是使用zip(cycle $ (0 &lt;$ [2..n]) ++ [1]),或者通过iteratesplitAt。 :)
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2018-03-07
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 1970-01-01
    相关资源
    最近更新 更多