如何使用列表推导在Haskell中创建此类列表

时间:2018-03-11 11:39:33

标签: list haskell list-comprehension

所以我需要创建这样的列表

[2,4,5,8,9,10,11,16,17,18,19,20,21,22,23,32 ..]

模式如下: 2 ^ 1,2 ^ 2,2 ^ 2 + 1,2 ^ 3,2 ^ 3 + 1,2 ^ 3 + 2,2 ^ 3 + 3 ..所以重复次数为(2 ^ n + 1, 2 ^ n +2 ..每次都加倍)我希望你明白了。 我可以使用Haskell中的函数创建这样的列表但我感兴趣是否可以单独使用列表理解

编辑:有些人让我展示一个解决这个问题的功能方法。这是

rep _ 0 = []
rep a b = a : rep (a+1) (b-1)
createlist a = rep (2^(a+1)) (2^a)  ++ createlist (a+1))

因此,如果我们说'取50(创建列表0),结果将是

[2,4,5,8,9,10,11,16,17,18,19,20,21,22,23,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82]

所以你总是需要用初始参数0来调用这个函数。这是一个非常讨厌的解决方案,我想让它变得更容易。

2 个答案:

答案 0 :(得分:4)

根据您的示例,列表如下所示:

 2
 4  5
 8  9 10 11
16 17 18 19 20 21 22 23
32 33 34 35 36 37 38 39 40 41 ...

因此,对于从1到无穷大的每个 i ,我们产生 [2 i ,2 i +范围内的元素2 I-1 。我们可以直接将其写入列表理解:

[ j | i <- [1..], j <- [2^i .. 2^i + 2^(i-1) - 1] ]

我们还可以让i获得2的幂,并在idiv (3*i) 2之间产生元素(不包括),所以:

[ j | i <- iterate (2*) 2, j <- [i .. div (2*i) 3 - 1] ]

我们也可以将其转换为列表monad,例如:

iterate (*2) 2 >>= \i -> [i..div (3*i) 2 - 1]

或更多无点(和无点):

import Control.Monad(ap)

iterate (*2) 2 >>= ap enumFromTo (pred . flip div 2 . (3 *))

答案 1 :(得分:0)

可以尝试使用 f i )函数编写列表的第i个 项,其中i&gt; = 0

整体无限列表可以表示为

L_0 ++ L_1 ++ L_2 ++ ...

其中每个L_n是形式的有限列表

L_n = [ 2^(n+1), 2^(n+1) + 1, ..., 2^(n+1) + (2^n - 1) ]

L_n的大小是2 ^ n我们知道对于任何k,2 ^ 0 + 2 ^ 1 + ... + 2 ^ k = 2 ^(k + 1) - 1(它是几何级数)因此,如果我们被要求找到无限列表中的 th 项的哪个有限列表,我们可以找到最高整数m,其中i> = 2 ^ m - 1.一旦这是完成后,我们可以肯定地说, th 术语在L_m中。我们说无限列表的i th 项是L_m的(i - 2 ^ m + 1) th 元素。

这允许我们将最终序列(让我们称之为“列表”)定义为

thatList :: [Int] thatList = [ f i | i <- [0..] ]

f :: Int -> Int f i = (2 ^ (m + 1)) + (i - (2 ^ m) + 1) where m = floor (logBase 2 (fromIntegral i + 1))