Haskell 理解不同的折叠状态

Haskell 理解不同的折叠状态,haskell,fold,equational-reasoning,Haskell,Fold,Equational Reasoning,我理解简单的foldr语句,比如 foldr (+) 0 [1,2,3] 然而,我在处理更复杂的foldr语句时遇到了麻烦,即在函数中包含两个参数的语句,以及/和-计算。有人能解释一下获得这些答案的步骤吗 foldr (\x y -> (x+y)*2) 2 [1,3] = 22 foldr (/) 2 [8,12,24,4] = 8.0 谢谢。折叠的函数参数总是包含两个参数(+)和(/)是二进制函数,与第二个示例中的函数类似 Prelude> :t (+) (+) :: Num

我理解简单的foldr语句,比如

foldr (+) 0 [1,2,3]
然而,我在处理更复杂的foldr语句时遇到了麻烦,即在函数中包含两个参数的语句,以及/和-计算。有人能解释一下获得这些答案的步骤吗

foldr (\x y -> (x+y)*2) 2 [1,3] = 22

foldr (/) 2 [8,12,24,4] = 8.0

谢谢。

折叠的函数参数总是包含两个参数
(+)
(/)
是二进制函数,与第二个示例中的函数类似

Prelude> :t (+)
(+) :: Num a => a -> a -> a
如果我们将第二个例子改写为

foldr f 2 [1,3]
    where
    f x y = (x+y)*2
我们可以使用与
(+)
完全相同的方案展开右侧折叠:


值得注意的是,
foldr
是右关联的,这显示了括号是如何嵌套的。相反,
foldl
,及其有用的近亲
foldl'
,是左关联的。
foldr
函数定义如下:

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ a []     = a
foldr f a (x:xs) = f x (foldr f a xs)

现在考虑下面的表达式:

foldr (\x y -> (x + y) * 2) 2 [1,3]
我们将为lambda命名:

f x y = (x + y) * 2
因此:

foldr f 2 [1,3]
-- is
f 1 (foldr f 2 [3])
-- is
f 1 (f 3 (foldr f 2 []))
-- is
f 1 (f 3 2)
-- is
f 1 10
-- is
22
同样地:

foldr (/) 2 [8,12,24,4]
-- is
8 / (foldr (/) 2 [12,24,4])
-- is
8 / (12 / (foldr (/) 2 [24,4]))
-- is
8 / (12 / (24 / (foldr (/) 2 [4])))
-- is
8 / (12 / (24 / (4 / (foldr (/) 2 []))))
-- is
8 / (12 / (24 / (4 / 2)))
-- is
8 / (12 / (24 / 2.0))
-- is
8 / (12 / 12.0)
-- is
8 / 1.0
-- is
8.0

希望有帮助。

您可以将
foldr
maybe
视为函数,用您选择的函数和/或值替换各自类型的数据构造函数:

data Maybe a = Nothing | Just a

maybe :: b -> (a -> b) -> Maybe a -> b
maybe  nothing _just Nothing  = nothing
maybe _nothing  just (Just a) = just a

data Either a b = Left a | Right b

either :: (a -> c) -> (b -> c) -> Either a b -> c
either  left _right (Left  a) = left  a
either _left  right (Right b) = right b

data List a = Cons a (List a) | Empty

foldr :: (a -> b -> b) -> b -> List a -> b
foldr cons empty = loop
  where loop (Cons a as) = cons a (loop as)
        loop Empty       = empty
因此,一般来说,您不必考虑涉及的递归,只需将其视为替换数据构造函数:

foldr f nil (1 : (2 : (3 : []))) == (1 `f` (2 `f` (3 `f` nil)))
foldr f nil (1 : (2 : (3 : []))) == (1 `f` (2 `f` (3 `f` nil)))