【问题标题】:What does foldr do in Haskell? [duplicate]foldr 在 Haskell 中做了什么? [复制]
【发布时间】:2016-05-01 14:50:52
【问题描述】:

所以我在 Haskell 中发现了 foldr 函数,根据我的经验,您可以使用它来计算列表的乘积和总和:

foldr f x xs

foldr (*) 1 [1..5] = 120
foldr (+) 0 [1..5] = 15

将数字添加到 x 部分会添加到总和或乘以最终乘积

foldr 实际上做了什么,为什么有人会使用它而不是内置函数“sum”或“product”等?

【问题讨论】:

  • foldr is 在很多方面 the 函数围绕 lists - 为什么你会使用它而不是 sumproduct?好吧,因为你可以用它来定义那些函数(但你是对的——你不会——你会用那些来提高可读性)
  • 除此之外还有很多个这样的问题——例如:stackoverflow.com/questions/1757740/how-foldr-works(可能重复)
  • 无论如何你都不会使用foldr 进行求和,你会使用foldl'

标签: haskell functional-programming


【解决方案1】:

sumproduct 本身是使用 fold 定义的(foldl,而不是 foldr,但我们现在先把这种区别放在一边),所以从某种意义上说,你 使用这些功能时使用折叠。同样orandconcat 以及更多也都使用折叠定义。所以这已经是折叠存在的一个原因:许多标准函数可以使用它们来定义,而不是冗余代码。

那么你什么时候会直接使用折叠呢?当做一些还没有特定功能的事情时,即当你想使用+*(或||&&++)以外的东西组合列表的元素时.

假设您有一个单数数字列表,并且您想将它们“连接”成一个数字:

concatDigits = foldl (\acc d -> d + acc * 10) 0

现在concatDigits [1,2,3] 给你123

或者你已经定义了一些数据结构并且你想将列表转换成它:

fromList = foldr insert empty`

事实上这就是fromList 对许多数据结构的常见定义。

【讨论】:

    【解决方案2】:

    Wikipedia entry 很好地说明了foldr 对列表的作用以及它与foldl 的区别。

    列表[1,2,3]由cons运算符(:)生成,空列表[]由这个表达式树生成:

        :
       / \
      1   :
         / \
        2   :
           / \
          3   []
    

    foldr f zf 替换 cons 运算符节点,用 z 替换空列表:

    相比之下,foldl f z 重新定向表达式树并将零元素重新定位在计算的另一端:

    一些观察:

    1. 注意foldr (:) [] 保持列表不变:

      foldr (:) [] [1..10] == [1..10]
      

    这是有道理的,因为我们只是将 cons 运算符替换为自身,并将空列表替换为空列表,因此不会更改任何内容。

    1. 如果我们用其他列表替换空列表,我们应该能够附加两个列表,例如:

      foldr (:) [9,8,7] [1,2,3] == [1,2,3,9,8,7]
      
    2. 可以考虑使用 cons 运算符将元素添加到列表中:

      (:) :: a -> [a] -> [a]
      

    如果我们将f 定义为:

        f :: Int -> [Int] -> [Int]
        f a as = [0] ++ [a] ++ as
    

    然后foldr f [] 将在输入列表的每个元素之前添加一个 0:

        foldr f [] [1,2,3] == [0,1,0,2,0,3]
    
    1. Data.Set 有一个函数insert,其签名在结构上类似于(:)

      insert :: Ord a => a -> Set a -> Set a
      

    确实,我们可以使用foldr将列表转换为集合

        import qualified Data.Set as S
    
        foldr S.insert S.empty [1,2,3]
    

    注意空列表是如何被空集替换的 - S.empty。 这是一次构建一个元素的数据结构的惯用方法 - 例如哈希映射、尝试、树等。

    【讨论】:

    • 我们通常使用foldl' 构建集合,但foldl' 是使用foldr 定义的。
    猜你喜欢
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 2011-06-05
    相关资源
    最近更新 更多