使用返回子列表的函数在haskell中创建无限递归列表

时间:2011-03-11 10:12:34

标签: haskell recursion

我正在尝试解决项目的问题。我想以整数螺旋形式创建元素列表。

我有这个功能:

next_four_numbers last size = map (\p -> last + p*(size-1)) [1,2,3,4]
  • 使用参数1和3返回[3,5,7,9]
  • 使用参数9和5返回[13,17,21,25]
  • 使用参数25和7返回[31,37,43,49] ......

我当然还有其他方法来生成它,但最后我希望有无限的序列:

diagonal_spiral_numbers = [1,3,5,7,9,13,17,21,25,31,37,43,49 ...]

我怎样才能使用“next_four_numbers”函数创建这个infinte序列?当然我希望它能够有效地映射这个(我希望能够做到这一点):

take 20000 ( filter is_prime diagonal_spiral_numbers )

谢谢,

ps:当然我正在学习haskell,它可能比我想象的要容易。

4 个答案:

答案 0 :(得分:4)

如果您有一个基于前一个生成下一个状态的函数,则可以使用iterate函数创建整个列表。在这种情况下,状态由四个数字和大小组成。调用iterate后,我调用map fst来删除size值,并调用concat来连接所有列表。

nextState (prev,size) = (next_four_numbers (last prev) size, size+2)
allNums = concat $ map fst $ iterate nextState ([1],3)

答案 1 :(得分:1)

你可以这样做:

diagonal_spiral_numbers =
    let helper l s =
            let next_four_numbers last size = map (\p -> last + p*(size-1)) [1,2,3,4]
                (a:b:c:d:[]) = next_four_numbers l s
            in  a:b:c:d : helper d (s+2)
    in  1 : helper 1 3

这里输出:

take 20 diagonal_spiral_numbers
[1,3,5,7,9,13,17,21,25,31,37,43,49,57,65,73,81,91,101,111]

但是我想知道你为什么需要使用next_four_numbers函数:结果列表可以用更简单的方式生成(我会说整体更好的)。

答案 2 :(得分:0)

当然可以这样做,生成一个列表列表然后flattening它(查看concatMap函数),但通常的方法是让你的帮助函数采用额外的“尾”参数,然后返回a:b:c:d:tail。

另一种方法是使用zipWith3。

答案 3 :(得分:0)

请注意,您的lastsize参数的格式始终分别为(2x+1)^22x+3x中的0,1,2,3,...

您只需要使用这些参数调用next_four_numbers一次。这可以通过列表理解来实现:

diagonals = [next_four_numbers ((2*x+1)*(2*x+1)) (2*x+3) | x <- [0..]]

或者使用地图(如果你对此感觉更舒服):

diagonals = map (\x -> next_four_numbers ((2*x+1)*(2*x+1)) (2*x+3)) [0..]

然后,这只是扁平化列表并在前面加1:

actual_diagonals = 1:concat diagonals
main = print (take 20 actual_diagonals)

这可能会被清理一下,但我会把它留给你;) 顺便说一下,[0..]只是无限列表0,1,2,3,...

的简写