在地图内递归调用

时间:2014-12-09 18:36:04

标签: haskell

具有以下功能:

between :: a -> [a] -> [[a]]
between i [] = [[i]]
between i r@(x:xs) = [[i]++r] ++ map f (between i xs)
                     where f = (\n->[x] ++ n)

between 0 [1,2]的结果是:

[[0,1,2],[1,0,2],[1,2,0]]

这怎么可能?我能够理解前两种情况:

    由于[0,1,2]
  • [[0]++[1,2]]
  • [1,0,2]因为map f [[0]++[2]](其中x是1)

地图是否也在递归?并保留对所有初始x的引用,以便它只是联系所有人?在我的脑海中,最终结果将是:

[[0,1,2],[1,0,2],[2,0]]

PS:“地图递归”也是一个很长的路线:

\n -> [1] + n
   \n ->[2] + n
      \n ->[3] + n
         \n ->[m] + n

2 个答案:

答案 0 :(得分:2)

首先,让我们修复此函数以使用cons(:)而不是++,因为前者在将元素添加到前面时更有效且惯用列表,它还可以简化相当多的功能:

between i [] = [[i]]
between i r@(x:xs) = (i : r) : map (x:) (between i xs)

这将更容易用于完成这些步骤:

between 0 [1, 2] =
    (0 : [1, 2]) : map (1:) (between 0 [2])
    [0, 1, 2] : map (1:) ((0 : [2]) : map (2:) (between 0 []))
    [0, 1, 2] : map (1:) ([0, 2] : map (2:) [[0]])
    [0, 1, 2] : map (1:) ([0, 2] : [[2, 0]])
    [0, 1, 2] : map (1:) [[0, 2], [2, 0]]
    [0, 1, 2] : [1:[0, 2], 1:[2, 0]]
    [0, 1, 2] : [[1, 0, 2], [1, 2, 0]]
    [[0, 1, 2], [1, 0, 2], [1, 2, 0]]

因此,通过等式推理,我们可以计算出GHC为达到这个答案所采取的步骤。

答案 1 :(得分:1)

但请记住,之间返回整个尾部的结果

between 0 [2]

给出

[[0, 2], [2, 0]]

f预先1应用于所有内容

[[1, 0, 2], [1, 2, 0]]

最后,我们添加[[i]++r](最好写成[i:r]

[[0, 1, 2], [1, 0, 2], [1, 2, 0]]