如果我这样调用函数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
[2,3,1,4]中的2,3,4
in [2,3,4,1]`,但我不确定是否可行,并且我不知道如何在haskell执行期间记录值。
换句话说,问题y
(列表的头)可以代表递归调用中的多个值吗?
在回答问题(如果相关)时,请确认/解释(x:y:ys)
in(x:y:ys) : map (y:) (interleave x ys)
仅代表一个列表(即[1,2,3,4-,并将整数参数插入第一个位置)。
(如果您可以显示func的执行顺序或将值如何存储在堆栈中,则可能会有所帮助)
实际上,递归调用的列表长度逐渐变短;但是,该函数会修改递归调用的结果以延长它们的长度。让我们从底部开始。对于空列表,没有有趣的事情发生:
interleave 1 []
= { first clause of definition }
[[1]]
但是到了包含一个元素的列表时,我们已经看到了有趣的事情。具体来说,由于递归调用的结果传递到map (y:)
,因此递归调用产生的简短列表每个都扩展一个元素。
interleave 1 [4]
= { list syntax }
interleave 1 (4:[])
= { second clause of definition }
(1:4:[]) : map (4:) (interleave 1 [])
= { recursive call, which produces short answers }
(1:4:[]) : map (4:) [[1]]
= { definition of map, which lengthens each answer }
(1:4:[]) : [4:[1]]
= { list syntax }
[[1,4],[4,1]]
以类似的方式,interleave 1 [3,4]
使递归调用interleave 1 [4]
产生[[1,4],[4,1]]
,但随后将map (3:)
其每个元素延长为[[3,1,4],[3,4,1]]
。
现在依次解决您的直接问题:
如果递归调用的list参数越来越短,那么列表的长度最终如何相同?
每次在较短的列表上进行递归调用时,递归调用的结果都将变长-精确地平衡了这些结果,以便interleave
使用长度n
列表进行调用将得到长度列表的集合n+1
。
y
(列表的头)可以在递归调用中表示多个值吗?
不,列表的开头始终是单个值。真正的魔力在于,每个递归调用都添加到头部上-因此您可以从许多递归调用中获得许多额外的头部。
确认/解释
(x:y:ys)
in(x:y:ys) : map (y:) (interleave x ys)
仅代表一个列表(即,[1,2,3,4-
in是在第一个位置插入整数参数的列表)。
正确。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句