【问题标题】:Extending a list of list in Haskell在 Haskell 中扩展列表
【发布时间】:2013-04-01 15:05:13
【问题描述】:

无论如何我可以在 Haskell 中扩展列表列表吗?

我正在尝试编写一个生成 [1,2,2,3,3,3,4,4,4,4.....] 的函数,它基本上是 1 one, 2 twos, 3三等奖。

我的尝试:

nnss :: [Integer]
nnss = [nPrint x x | x <- [1,2..]]

我尝试的问题是nPrint x x 返回一个整数列表,例如,nPrint 2 2 将返回 [2, 2]。无论如何我可以将列表从 [1,2,3...] 扩展到 [1,2,2,3,3,3...] 吗?

【问题讨论】:

  • nPrint 是一个坏名字(打印是一个 IO 动作),你使用的基本上只是replicate

标签: list haskell list-comprehension


【解决方案1】:

我们正在寻找的函数签名是 [[a]] -&gt; [a],如果我们检查 hoogle,我们会发现 concat 就是我们正在寻找的。​​p>

但在这种情况下,列表推导是不必要的,因为我们只是迭代每个项目,所以我们真的只想做一个map。因此,既然将mapconcat 结合起来很常见,我们可以写

concatMap (\x -> nPrint x x) [1..]

如果你是 haskell 的新手,你可以忽略它,但由于列表 monad 是用 concatMap 定义的,我们也可以写

[1..] >>= \x -> nPrint x x

【讨论】:

  • 如果我们真的想打 Haskell 高尔夫球,我们可以做 [1..] &gt;&gt;= join replicate,使用上面 leftaroundabout 建议的 replicate 和来自 Control.Monadjoin 函数(在这种情况下为 ((-&gt;) r) monad 实例,类型为(r -&gt; r -&gt; a) -&gt; r -&gt; a)。
【解决方案2】:

您也可以不使用映射和列表连接来编写它(只需在恒定时间内添加):

nnss :: [Integer]
nnss = genRepeated 1 1

genRepeated :: Integer -> Integer -> [Integer]
genRepeated x 0 = genRepeated (x+1) (x+1)
genRepeated x y = x : genRepeated x (y-1)

take 22 nnss == [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,6,6,6,6,6,6,7]

其他快速的可能性是:

nnss :: [Integer]
nnss = flatten [take x $ repeat x | x <- [1..]]

flatten :: [[a]] -> [a]
flatten [] = []
flatten ([]:xs) = flatten xs
flatten ((x:xs):ys) = x : flatten (xs:ys)

【讨论】:

  • 当我分析它时,这些都比我上面的慢
  • @jozefg 哦,它是渐近还是恒定时间慢?你知道这是为什么吗?我并不是说它更快,只是对初学者更友好,但我对造成差异的原因很感兴趣。
  • 仅供参考,您的自定义函数 flatten 只是 concat: hackage.haskell.org/packages/archive/base/latest/doc/html/…
【解决方案3】:

只需添加concat:

nnss :: [Integer]
nnss = concat [nPrint x x | x <- [1,2..]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-04
    • 2023-04-03
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    相关资源
    最近更新 更多