首页 文章

列表的头部是否可以代表多个值

提问于
浏览
4

如果我调用函数 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 回答

  • 4

    递归调用的列表长度确实逐渐缩短;但是,该函数修改递归调用的结果以延长它们 . 让我们从底层 Build 起来 . 对于空列表,没有任何有趣的事情:

    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参数越来越短,那么列表最终的长度是多少?

    每次对较短列表进行递归调用时,递归调用的结果都会变得更长 - 这些都是完全 balancer 的,因此调用 interleave 和length_ n 列表将导致长度为 n+1 列表的集合 .

    y(列表的头部)在递归调用中表示多个值吗?

    不,列表的头部始终是单个值 . 真正的魔力是每个递归调用都会添加到头部 - 所以你可以通过许多递归调用获得许多额外的头部 .

    确认/解释(x:y:ys)中的(x:y:ys):map(y :)(interleave x ys)是否只表示一个列表(即它是[1,2,3,4] - 在第一个位置插入整数参数) .

    正确 .

相关问题