【问题标题】:Functional Programming-Style Map Function that adds elements?函数式编程风格的 Map 添加元素的函数?
【发布时间】:2015-09-28 17:03:44
【问题描述】:

我知道并喜欢我的 filtermapreduce,它们恰好是越来越多并非真正纯粹功能性的语言的一部分。

我发现自己需要一个类似的功能:类似map,但不是一对一,而是一对多。

即原始列表的一个元素可能会映射到目标列表中的多个元素。

是否已经有类似的东西了,还是我必须自己推出?

【问题讨论】:

  • 我不了解 Haskell,但这不等于 map 返回一个对象数组然后 reduce 将它们连接在一起吗?
  • 顺便说一下,既然您提到了filtermap,请注意,这两者都可以根据您描述的“一对多”操作来实现(如 cmets 所示,是concatMap,或>>=)。你可能会喜欢用它来实现filtermap

标签: haskell functional-programming


【解决方案1】:

这正是 >>= 专门针对列表所做的。

> [1..6] >>= \x -> take (x `mod` 3) [1..]
[1,1,2,1,1,2]

这是concatenating 的结果

> map (\x -> take (x `mod` 3) [1..]) [1..6]
[[1],[1,2],[],[1],[1,2],[]]

【讨论】:

  • 如果你不喜欢奇怪的符号,你可以使用concatMap
  • @JoachimBreitner,但是你错过了与树木嫁接和所有其他单子善良的联系。
  • 当然,但我觉得先指向concatMap,然后再指出(>>=)=concatMap,作为对那些可以使用它的人的评论更自然。
【解决方案2】:

您不必自己动手。这里有很多相关的功能,但我会强调三个。

首先,concat function 已经包含在 Prelude(默认加载的标准库)中。当应用于列表列表时,此函数的作用是返回包含子列表连接内容的列表。

练习:编写您自己的concat :: [[a]] -> [a]

所以使用concatmap,你可以写出这个函数:

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f

...除了您实际上不需要编写它,因为它是如此常见的模式,the Prelude already has it(比我在这里展示的更通用的类型——库版本采用任何 Foldable,而不是只是列表)。

最后还有Monad的list实例,可以这样定义:

instance Monad [] where
  return a = [a]
  as >>= f = concatMap f as

所以>>= 运算符(Monad 类的核心)在处理列表时与concatMap 完全相同。

练习:浏览Data.List module 的文档。弄清楚如何将模块导入您的代码并使用其中的一些功能。

【讨论】:

  • 感谢您的解释和练习——我喜欢它!
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 2016-11-25
  • 2016-01-11
相关资源
最近更新 更多