【问题标题】:Explanation of map functions (using foldr) in Haskell?Haskell中地图功能的解释(使用foldr)?
【发布时间】:2020-04-29 12:38:50
【问题描述】:

我正在尝试使用 foldr 定义地图功能

我找到了以下两个解决方案,但我不太确定它们是如何工作的。

map' :: (a -> b) -> [a] -> [b]
map' f = foldr ((:) . f) []
map'' :: (a -> b) -> [a] -> [b]
map'' f  = foldr (\x xs -> f x : xs) []

我对 Haskell 和 foldr 还很陌生,所以我很难理解第一个解决方案中的 ((:) . f) 和第二个解决方案中的 (\x xs -> f x : xs) 的作用。

我也不明白 foldr 是如何处理空列表的。

如果我能用外行的术语简单一步一步地解释这一点,将不胜感激。

【问题讨论】:

  • (:) . f\x xs -> f x : xs 是等价的。
  • 表达式\x xs -> f x : xslambda expression(:) . f 是它的pointfree 版本。
  • \x xs -> f x : xs == \x xs -> (:) (f x) xs == \x -> (:) (f x) == (:) . f.
  • 你明白(:) 是做什么的吗?或.?或者什么是 lambda 表达式?或者什么是 lambda 函数?这些都是这个问题的真正先决条件。尝试一次问一个问题。然后是foldr 标签。尝试探索它。维基百科上也有一个页面。尝试查看 stackoverflow.com/tags/haskell/info 以获取学习 Haskell 的资源。

标签: function haskell higher-order-functions


【解决方案1】:

(\x xs -> f x : xs)(:) . f 的含义相同。它们都是接受两个参数的函数,将f 应用于第一个参数,然后将其应用于第二个参数。

那么foldr 在给定一个空列表时会做什么?它只返回起始值,在这些示例中为[]

这里是foldr 来自Hackage 的实现:

foldr k z = go
          where
            go []     = z
            go (y:ys) = y `k` go ys

【讨论】:

  • in (\x xs -> f x : xs) [ ] 如果只提供空列表作为起始值,它如何接受两个参数? x 会变成 [ ] 吗?你从哪里得到 xs?
  • 实际上,(\x xs -> f x : xs) 没有在此处提供任何参数。它被作为参数提供给foldr,后者稍后会调用它。我已经编辑了答案以引用foldr 的实现,这可能会对您有所帮助。 lambda 最终成为 foldr 定义中的函数 k
  • 可能值得更改为foldr 的更简单定义。更复杂的方法更适合 ghc 优化事物的方式,但涉及额外的定义会使初学者更难将所有内容都牢记在心。
  • @Carl 我认为有一个合理的后续问题,“为什么以这种方式定义 foldr?” (我相信这里已经被问到了)。但我认为暗示它的定义方式并非如此是有害的。
  • 我们不必这么建议。我们可以说它的定义使得以下等式成立:foldr f z [x1, x2, ..., xn] == x1 ‘f‘ (x2 ‘f‘ ... (xn ‘f‘ z)...)(这意味着foldr f z [] == z)。这就是Haskell 2010 report 正在做的事情。
猜你喜欢
  • 1970-01-01
  • 2021-04-15
  • 1970-01-01
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多