当我们尝试使用foldr附加两个列表时,为什么要切换列表顺序?

时间:2018-06-12 10:40:01

标签: haskell fold

我看到post解释了如何使用foldr附加两个列表。

但我不明白为什么要切换列表的顺序。

append xs ys = foldr (\x y -> x:y) ys xs

第一步将是

[y,x] (\x y -> x:y) foldr (\x y -> x:y) ys' xs'

我说错了吗?那么结果会将ys放在xs前面吗?

不应该是

append xs ys = foldr (\x y -> x:y) xs ys

3 个答案:

答案 0 :(得分:4)

  

第一步将是

[y,x] (\x y -> x:y) foldr (\x y -> x:y) ys' xs'

这不是一个有效的Haskell表达式,但我认为你在这里表达的意思是你从每个列表中取一个元素,然后以某种方式将它们插入前面。这不是foldr的工作原理 - 它不会迭代z参数的元素(在这种情况下为ys) - 实际上该参数甚至不必是列表。

相反foldr f z (x:xs')扩展如下:

x `f` foldr f z xs'

foldr f z []扩展为z

所以在你的情况下,第一步是:

x : foldr (\x y -> x:y) ys xs'

这将一直持续到我们到达空列表为止,在这种情况下ys将成为结果。所以:

  foldr (\x y -> x:y) ys [x1, x2, ..., xn]
= x1 : foldr (\x y -> x:y) ys [x2, ..., xn]
= x1 : x2 : foldr (\x y -> x:y) ys [..., xn]
= ...
= x1 : x2 : ... : xn : foldr (\x y -> x:y) ys []
= x1 : x2 : ... : xn : ys

从中您可以看到xs的元素放在ys之前。

答案 1 :(得分:2)

第一步不是那样的。检查foldr的类型

    ghci>:t foldr
    foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b

为了简化,我们假设t[]。在这种情况下,foldr是:

给我一​​个f函数,其中包含ab并返回b。给我一个初始元素和a列表。我会产生一个b

因此,它的工作方式是:获取列表的最后一个元素并将f应用于该元素,并将初始值生成b。获取列表的新的最后一个值并将f应用于该值以及之前的结果......依此类推。

在您的情况下,初始元素实际上是一个列表,而且非常混乱。但检查一下这个计算。请记住,[1,2,3]用作初始值,因此我们不会循环播放"在它上面

    foldr (\x y -> x:y) [1,2,3] [4,5,6]
    foldr (\x y -> x:y) 6:[1,2,3] [4,5]
    foldr (\x y -> x:y) 5:6:[1,2,3] [4]
    foldr (\x y -> x:y) 4:5:6:[1,2,3] []

希望它有所帮助!

答案 2 :(得分:1)

直觉是{​​{1}}"取代"每个foldr c n list位于: listc位于[]

n附加xs,需要"替换" ys[] xs ys。相反,:应该替换为自己。

因此,我们得到foldr (:) ys xs