【问题标题】:Haskell function to apply operations recursively to an argumentHaskell 函数以递归方式将操作应用于参数
【发布时间】:2015-09-12 17:29:02
【问题描述】:

Haskell 中是否有内置函数可以递归地将操作列表应用于参数?

我有一个适用于Double 的操作列表(乘法、加法……),我只想得到结果。 例如:

operationList = [
                  (\v -> v/8+2)
                , (\v -> v-12)
                , (\v -> v*v)
                ]

func operationList 3

func 应该返回 92,640625

我在 hoogle 中搜索了签名 [(a -> a)] -> a -> a,但没有找到任何东西。

【问题讨论】:

    标签: haskell ghc


    【解决方案1】:

    有(至少)两种方法可以解决这个问题。一种是将每个函数应用于应用前一个函数的结果。这给了你:

    foldr ($) 3 (reverse operationList)
    

    另一种是首先将所有函数组合在一起,然后将结果函数应用于参数:

    foldr (.) id (reverse operationList) 3
    

    组合下函数的这种行为也被Endo monoid 捕获:

    appEndo (foldMap Endo (reverse operationList)) 3
    

    列表必须颠倒,因为 foldr 从“右向左”折叠:

    foldr ($) 3 [f,g,h]
    = { definition of foldr }
    f $ g $ h $ 3
    = { definition of ($) }
    f (g (h 3))
    
    foldr (.) id [f,g,h] 3
    = { definition of foldr }
    (f . g . h . id) 3
    = { definition of (.), definition of id, eta reduction }
    f (g (h 3))
    

    【讨论】:

    • 您永远不必反转列表来折叠它。 foldr f n (reverse xs) = foldl (flip f) n xs 如果我没记错的话。
    • 我相信foldMap (Dual . Endo) 是使用Foldable 的方式。
    • @dfeuer 是的,但从概念上讲,foldl 版本要复杂得多。我想了解基本概念,而不是停留在管理上。不过Dual 版本相当不错。此外,我怀疑 OP 可以控制实际应用程序中的列表顺序,因此不需要反向操作。
    【解决方案2】:
    \> foldr ($) 3 (reverse operationList)
    92.640625
    

    \> foldl (flip ($)) 3 operationList
    92.640625
    

    【讨论】:

      猜你喜欢
      • 2011-02-14
      • 2019-02-28
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 2010-10-13
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      相关资源
      最近更新 更多