【问题标题】:How to rewrite a fold with anonymous function in Haskell into a regular function?如何将 Haskell 中带有匿名函数的折叠重写为常规函数?
【发布时间】:2020-03-07 18:04:54
【问题描述】:

我正在尝试使用 Haskell 自学函数式编程。

我很难理解 currying 和 lambdas。

这是一个生成列表前缀列表的函数(输出列表列表)。

foldr (\element accumulator -> [] : map (element:) accumulator) [[]]

我正在尝试将其重写为没有 lambda 的常规函数​​,以帮助我了解 lambda 的工作原理。我该怎么做?我被困住了。我需要一个辅助功能吗?谢谢。

【问题讨论】:

  • 如果折叠抽象让您感到困惑,请仅通过递归来表达

标签: haskell lambda functional-programming fold currying


【解决方案1】:

是的,您将需要一个辅助函数。 where 子句是放置此类助手的好地方。 where 子句附加到定义,所以我需要为你的函数命名(我已将其命名为inits)。首先将表达式逐字移出。

inits :: [a] -> [[a]]
inits = foldr helper [[]]
    where
    helper = \element accumulator -> [] : map (element:) accumulator

然后你可以将右边的 lambda 参数移动到左边的参数绑定,这意味着同样的事情:

inits :: [a] -> [[a]]
inits = foldr helper [[]]
    where
    helper element accumulator = [] : map (element:) accumulator

(你也可以只做一个参数:

    helper element = \accumulator -> [] : map (element:) accumulator

这些都是等价的。)

【讨论】:

  • @noobie 请参阅下面 Will Ness 的回答。
  • @noobie, where 只是帮助您组织命名空间的便利。也可以使用let 或在顶层完成。
【解决方案2】:

听起来你在寻找pointfree 表单。是的,可以做到。

inits :: [a] -> [[a]]
inits = foldr ((([]:).) . map . (:)) [[]]

Try it online!

您的 lambda 已变成 (([]:).) . map . (:)。不是很漂亮吧?而且很多更难理解。我建议你避免使用这种方法。

【讨论】:

    【解决方案3】:

    一般来说,

    foldr g [[]] []            =  [[]]
    foldr g [[]] [a,b,c, ...]  =  g a (foldr g [[]] [b,c, ...]) 
    

    你的函数 g( \ x y -> [] : map (x:) y )

                        g x y  =  [] : map (x:) y
    

    因此与您的g 我们有

    foldr g [[]] [a,b,c, ...]  =  [] : map (a:) (foldr g [[]] [b,c, ...])
    

    foldr g [[]] 替换为foo,并将伪代码[a,b,c, ...] 替换为有效模式(a:bc),我们得到

    foo          []            =  [[]]
    foo          (a:bc)        =  [] : map (a:) (foo           bc       )
    

    这是没有 lambda 且没有 where 子句的“常规函数”。

    【讨论】:

      猜你喜欢
      • 2021-04-19
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 2013-01-11
      • 2019-10-08
      • 1970-01-01
      相关资源
      最近更新 更多