【问题标题】:The missing folds缺失的褶皱
【发布时间】:2017-12-05 17:55:53
【问题描述】:

如果您想折叠列表,我看到了四种方法。

从列表右侧折叠,递归项在右侧

foldrr (-) 100 [1..10] = 1 - (2 - (3 - (4 - (5 - (6 - (7 - (8 - (9 - (10 - (100))))) )))))) = 95

foldrr :: (a -> b -> b) -> b -> [a] -> b
foldrr step zero (x:xs) = step x (foldrr step zero xs)
foldrr _    zero []     = zero

从列表右侧折叠,递归项在左侧

foldrl (-) 100 [1..10] = (((((((((((100) - 10) - 9) - 8) - 7) - 6) - 5) - 4) - 3 ) - 2) - 1 = 45

foldrl :: (a -> b -> a) -> a -> [b] -> a
foldrl step zero (x:xs) = step (foldrl step zero xs) x
foldrl _    zero []     = zero

从列表左侧折叠,递归项在右侧

foldlr (-) 100 [1..10] = 10 - (9 - (8 - (7 - (6 - (5 - (4 - (3 -) (2 - (1 - (100))))) )))))) = 105

foldlr :: (a -> b -> b) -> b -> [a] -> b
foldlr step zero (x:xs) = foldlr step (step x zero) xs
foldlr _    zero []     = zero

从列表左侧折叠,递归项在左侧

foldll (-) 100 [1..10] = (((((((((((100) - 1) - 2) - 3) - 4) - 5) - 6) - 7) - 8 ) - 9) - 10 = 45

foldll :: (a -> b -> a) -> a -> [b] -> a
foldll step zero (x:xs) = foldll step (step zero x) xs
foldll _    zero []     = zero

这些折叠中只有两个作为 foldrfoldl 进入 Prelude。是否有任何理由只包含两个折叠,为什么要包含这两个?

【问题讨论】:

    标签: haskell recursion fold language-features haskell-prelude


    【解决方案1】:

    foldrlfoldlr 不增加任何表现力:它们与其他两个折叠相同,但折叠功能翻转。

    foldrl f = foldr (flip f)
    foldlr f = foldl (flip f)
    
    -- Or this, if you prefer
    foldrl = foldr . flip
    foldlr = foldl . flip
    

    但是根据foldr 来定义foldl 并不是那么容易,因此同时提供它们是有用的。

    【讨论】:

    • 为什么foldr (flip f)foldl 对于非交换的- 操作总是产生相同的结果,而foldl (flip f)/foldr 却没有?
    • @ftor 因为- 遵循身份(a-b)-c = (a-c)-b。一般来说,所有四个结果都可能不同,但- 不会。
    • @ftor,有一个具有这种性质的通用身份:foldl f b xs = foldr (flip f) b (reverse xs)。对于有限列表,foldr c n xs = foldl (flip c) n (reverse xs).
    • 另一个永远存在的:foldr c n (reverse xs) = foldl (flip c) n xs.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 2016-12-17
    • 2012-12-06
    • 2021-02-07
    • 2022-08-21
    相关资源
    最近更新 更多