foldr和foldr1 Haskell

Mad*_*ote 3 haskell fold

我试图深入研究,考虑到它对我来说似乎是一个非常强大的资产.但是,你能帮我解决这个问题:

foldr  (/) 2 [1,2,3] -- (1/(2/(3/2))), result 0,75 {where 2 is base)
foldr1 (/)   [2,2,3] -- (1/(2/(3/2))), result 3.00 {where 2 is base)
Run Code Online (Sandbox Code Playgroud)

我认为我正在认真监督褶皱之间的本质区别.谢谢

Wil*_*sem 6

foldr :: (a -> b -> b) -> b -> [a] -> b 具有实现:

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
Run Code Online (Sandbox Code Playgroud)

因此,这意味着如果我们输入foldr f z [x1, x2, x3],则其值为:

   foldr f z [x1, x2, x3]
-> f x1 (foldr f z [x2, x3])
-> f x1 (f x2 (foldr f z [x3]))
-> f x1 (f x2 (f x3 (foldr f z [])))
-> f x1 (f x2 (f x3 z))
Run Code Online (Sandbox Code Playgroud)

因此,对于您的示例,结果将为:

  (/) 1 ((/) 2 ((/) 3 2))
= 1 / (2 / (3 / 2))
= 1 / (2 / 1.5)
= 1 / 1.33333...
= 0.75
Run Code Online (Sandbox Code Playgroud)

foldr1 :: (a -> a -> a) -> [a] -> a函数几乎相似,除了在看到一个1元素列表的情况下,我们返回该元素,所以区别是:

foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 _ [x] = x
foldr f (x:xs) = f x (foldr1 f xs)
Run Code Online (Sandbox Code Playgroud)

因此,这意味着foldr1 f [x1, x2, x3]我们得到:

   foldr1 f [x1, x2, x3]
-> f x1 (foldr1 f [x2, x3])
-> f x1 (f x2 (foldr1 f [x3]))
-> f x1 (f x2 x3))
Run Code Online (Sandbox Code Playgroud)

因此,对于示例输入,我们得到:

  (/) 2 ((/) 2 3)
= 2 / (2 / 3)
= 2 / 0.6666...
= 3.0
Run Code Online (Sandbox Code Playgroud)

因此,如果zxi类型相同,则foldr f z [x1, ..., xn]等于foldr1 f [x1, ..., xn, z]


And*_*kin 6

一般来说

foldr1 op [y1, ..., yn, x]
Run Code Online (Sandbox Code Playgroud)

与...基本相同

foldr op x [y1, ..., yn]
Run Code Online (Sandbox Code Playgroud)

只要n >= 1.也就是说,在你的特殊情况下

foldr1 (/) [2, 2, 3]
Run Code Online (Sandbox Code Playgroud)

将评估为2/(2/3) = 3.

有了除法运算符,它有点无聊,因为

foldr1 (/) [y, y, x1, ... , xn]
  = y/(y/(foldr1 (/) [x1, ..., xn]))
  = foldr1 (/) [x1, ..., xn]
Run Code Online (Sandbox Code Playgroud)

为了所有人n >= 1.所以,在你的例子中,它应该只返回结果

foldr1 (/) [3]
Run Code Online (Sandbox Code Playgroud)

当然3.0,这确实是评价的3.0.

这是一个不那么退化的例子:

foldr1 (/) [2, 3, 5, 7] --  evals to 0.47619047619047616
Run Code Online (Sandbox Code Playgroud)

在这里,它给出了相同的结果2 / (3 / (5 / 7)),而结果与之相同

foldr (/) 7 [2, 3, 5]
Run Code Online (Sandbox Code Playgroud)

我希望它能略微澄清评估的顺序.