6

我最近遇到了这篇关于函数式编程不同方面的有用资源的帖子,例如 monads 和 monoids 等。

但问题是——普通程序员可以从这些概念中得到什么用处。我经常遇到关于这些问题的“学术”研究。但是,我在实践中(在实际项目中)从未遇到过使用它们的人。

所以问题是 - Haskell 中是否有任何广泛使用的开源项目真正利用了这些东西,这些项目证明了这个概念在“生产”软件中的实际必要性,而不是在编写的“学术”软件中”纯娱乐”。制作这样的列表会很酷:

  • Monads - 用于 A 和 B 等项目,否则这样的代码看起来会复杂得多。
  • 对幺半群也是如此。
  • 函子也是如此。
  • 箭也是一样。
4

3 回答 3

9

许多这些概念在 Haskell 代码中是如此隐含,因此更容易列出不使用它们的示例(假设您可以找到一个)。每个 Haskell 程序都使用 monad,至少对于 IO。

所有这些都被广泛使用,因为它们是在代码中经常出现的抽象。考虑函子:对容器进行映射是一种相当普遍的需求,因此为任何类似容器的数据结构提供单一接口是有意义的,这正是 Functor 提供的。碰巧即使是“容器”的概念也比函子抽象更具体,但希望这能证明这一点。

Monads:XMonad窗口管理器是一个广泛使用的程序,它大量使用了 monad 转换器和zipper 结构STM是一个库,它提供了一个具有有用属性的新 monad。

Monoids:包中的Sequence结构是用 monoids 实现的。此外,monoids 被广泛用于对集合、列表等进行建模,因为这两个 monoid 操作提供了一个空列表和连接(或空集和联合)。containers

箭头:立即想到YampaHXT (Haskell XML 工具箱)。

函子无处不在。monadic 代码有很多<$>s 是很常见的,这意味着该Functor实例正在使用中。 大多数 Haskell 解析器大量使用函子。

于 2011-11-28T13:34:43.843 回答
6

Ertes 的回答和 John L 的回答都很棒。我只是想补充一些关于函子和幺半群的东西:我相信 Haskell 的大部分术语,虽然在其精确度上是好的,但对于新的 Haskell 程序员来说可能有点反感。我总是告诉新手,幺半群可以被认为是“可附加的”,而函子可以被认为是“可映射的”。显然,这种简化有一些损失,但它有助于克服语言最初的词汇障碍。monoid 接口(typeclass)具有“append”和“identity”函数,而 functor 只指定了一个 map 函数。附加和映射的长期思想之间存在一些滑移(例如求和是一种附加),但基本思想是成立的。

作为附加和映射的简单接口,monoids 和 functor 很快就显示出它们有很多用途:任何时候你的数据结构需要支持附加或映射,你有时间让你的数据结构成为 monoid 或 functor 的实例可以简化过程。

希望这会有所帮助。

之后,这里是您询问的库列表。

Functors:看看像 attparsec 这样的解析库。http://hackage.haskell.org/package/attoparsec-0.10.0.2函子让您可以轻松地编写解析器,以便您可以为复杂的数据编写易于编写、易于阅读的解析器。将 attoparsec 解析器与可比较的正则表达式进行对比!

Monoid:查看任何数组、向量库 ( http://hackage.haskell.org/packages/archive/vector/0.9/doc/html/Data-Vector.html ) 以了解 Monoid 用于实现 monoid 的可附加性. 此外,这是一篇很棒的文章,可以让 monoids 为您工作http://blog.sigfpe.com/2009/01/haskell-monoids-and-their-uses.html

Monads:查看 Data.Binary - 一个简单且基本的 Haskell 库 - 以获得 Monads 的完美用例。http://hackage.haskell.org/packages/archive/binary/0.4.1/doc/html/Data-Binary.html通过使用 monads,您可以编写一系列复杂的指令来以几乎命令式的方式解析二进制文件.

于 2011-11-28T13:45:28.857 回答
6

我在现实世界的应用程序中有效地使用箭头和单子(因此也是函子)。我的函数响应式编程(FRP)库Netwire结合了你提到的所有四个概念以及更多,FRP 本身也是一种设计模式,你通常从学术界知道。这些是使用的概念:

  • 箭头和箭头转换器:Netwire 提供Wire类型,它是一个箭头转换器。
  • Monad 和 monad 转换器:Wire通常会转换成一堆被Kleisli箭头包裹的 monad 转换器。
  • 线抑制(如异常或未发生的事件)使用一个幺半群。

第 3 版即将发布(我希望是今天),它还将(非关联)类型家庭带入游戏。

于 2011-11-28T12:09:29.747 回答