哈斯克尔的折叠:混乱

时间:2017-05-01 03:06:47

标签: haskell

我对foldr的用法有疑问。

说我想以这种方式使用foldr:

foldr (\x y -> (x + y)/2) 2 [4,5,6]

在这种情况下y代表列表的每个元素吗?

特别是,让我们打开这个功能。

我们有(x = 2,y = 6) - > (2 + 6)/ 2 = 4.

接下来,我们有x = 4,y = 5吗?

我问的是我真正想问的简化版。这里,x和y的内容很重要,因为在我的应用程序中,我有一个函数将第一个参数作为类型a,第二个参数作为类型b。因此,我确实需要了解最新情况。

2 个答案:

答案 0 :(得分:2)

  

说我想以这种方式使用foldr:

foldr (\x y -> (x + y)/2) 2 [4,5,6]
     

在这种情况下y代表列表的每个元素吗?

解决问题的一种方法是查看foldr的类型:

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

折叠的结构对于某些t a类型Foldable t(在您的情况下,您有一个列表,因此t[]),其元素包含a输入b。通过折叠累积的结果具有类型a -> b -> b。用于折叠的二进制函数具有类型{{1}},因此元素作为第一个参数传递,累积值作为第二个参数传递。

另一种解决方法是阅读the actual implementation of foldr for lists(我通过查找Foldable instance of lists找到了这个,然后点击源链接)。您可能想尝试一下,看看一张图片如何与另一张图片对应。

答案 1 :(得分:1)

foldr f startingValue (x:xs)扩展为f x (foldr f startingValue xs)foldr f startingValue []扩展为startingValue,所以在您的情况下:

foldr (\x y -> (x + y)/2) 2 [4,5,6]
(\x y -> (x + y)/2) 4 (foldr (\x y -> (x + y)/2) 2 [5,6])
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 (foldr (\x y -> (x + y)/2) 2 [6]))
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 ((\x y -> (x + y)/2) 6 (foldr (\x y -> (x + y)/2) 2 [])))
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 ((\x y -> (x + y)/2) 6 2))
(\x y -> (x + y)/2) 4 ((\x y -> (x + y)/2) 5 4)
(\x y -> (x + y)/2) 4 4.5
4.25

使用f x y = (x + y)/2可能更容易看到:

foldr f 2 [4,5,6]
f 4 (foldr f 2 [5,6])
f 4 (f 5 (foldr f 2 [6]))
f 4 (f 5 (f 6 (foldr f 2 [])))
f 4 (f 5 (f 6 2))
f 4 (f 5 4)
f 4 4.5
4.25

如果您了解如何构建利弊列表(使用:),您可以将foldr视为将所有:替换为您提供的功能。