如果我调用函数 interleave
(定义如下 - 它是一个在列表的每个位置插入数字(或任何类型)的函数),这样生成的列表都是相同的长度
interleave 1 [2,3,4]
[[1,2,3,4],[2,1,3,4],[2,3,1,4],[2,3,4,1]]
但是,我期望列表长度越来越短,因为对 interleave
的递归调用将列表减去头部(即只有 ys
) . 由于列表的尾部随着每次调用而变得越来越短,我希望结果列表更短 .
interleave :: a -> [a] -> [[a]]
interleave x [] = [[x]]
interleave x (y:ys) = (x:y:ys) : map (y:) (interleave x ys)
如果递归调用的list参数越来越短,那么列表如何最终成为相同的长度?
我能想象的唯一答案是映射值 map (y:)
代表递归调用中的多个数字(即它是[2,1,3,4]中的2和[2,3,1,4]中的 2,3
和[2,3,4,1]中的 2,3,4
,但我可能是'm not sure if that',我不知道如何在haskell执行期间记录值 .
问题,换句话说, y
(列表的头部)在递归调用中表示多个值?
在回答问题时(如果它是相关的),请确认/解释 (x:y:ys) : map (y:) (interleave x ys)
中的 (x:y:ys)
是否只代表一个列表(即它是[1,2,3,4-并且整数参数插入第一个位置) .
(如果您可以显示func的执行顺序,或者值如何存储在堆栈中,这可能会有所帮助)
1 回答
递归调用的列表长度确实逐渐缩短;但是,该函数修改递归调用的结果以延长它们 . 让我们从底层 Build 起来 . 对于空列表,没有任何有趣的事情:
但是当我们到达包含一个元素的列表时,我们已经看到了有趣的事情发生了 . 具体来说,由于递归调用的结果传递给
map (y:)
,递归调用产生的短列表每个都被一个元素扩展 .以类似的方式,
interleave 1 [3,4]
使递归调用interleave 1 [4]
生成[[1,4],[4,1]]
,但随后使用map (3:)
将其中的每个元素延长为[[3,1,4],[3,4,1]]
.现在依次解决您的直接问题:
每次对较短列表进行递归调用时,递归调用的结果都会变得更长 - 这些都是完全 balancer 的,因此调用
interleave
和length_n
列表将导致长度为n+1
列表的集合 .不,列表的头部始终是单个值 . 真正的魔力是每个递归调用都会添加到头部 - 所以你可以通过许多递归调用获得许多额外的头部 .
正确 .