翻译连载 | 附录 B: 谦虚的 Monad-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱;分享,是 CSS 里最闪耀的一瞥;总结,是 JavaScript 中最严谨的逻辑。经过捶打磨练,成就了本书的中文版。本书包含了函数式编程之精髓,希望可以帮助大家在学习函数式编程的道路上走的更顺畅。比心。

译者团队(排名不分先后):阿希、blueken、brucecham、cfanlife、dail、kyoko-df、l3ve、lilins、LittlePineapple、MatildaJin、冬青、pobusama、Cherry、萝卜、vavd317、vivaxy、萌萌、zhouyao

JavaScript 轻量级函数式编程 附录 B: 谦虚的 Monad

首先,我坦白:在开始写以下内容之前我并不太了解 Monad 是什么。我为了确认一些事情而犯了很多错误。如果你不相信我,去看看 这本书 Git 仓库 中关于本章的提交历史吧!

我在本书中囊括了所有涉及 Monad 的话题。就像我写书的过程一样,每个开发者在学习函数式编程的旅程中都会经历这个部分。

尽管其他函数式编程的著作差不多都把 Monad 作为开始,而我们却只对它做了简要说明,并基本以此结束本书。在轻量级函数式编程中我确实没有遇到太多需要仔细考虑 Monad 的问题,这就是本文更有价值的原因。但是并不是说 Monad 是没用的或者是不普遍的 —— 恰恰相反,它很有用,也很流行。

函数式编程界有一个小笑话,几乎每个人都不得不在他们的文章或者博客里写 Monad 是什么,把它拎出来写就像是一个仪式。在过去的几年里,人们把 Monad 描述为卷饼、洋葱和各种各样古怪的抽象概念。我肯定不会重蹈覆辙!

一个 Monad 仅仅是自函子 (endofunctor) 范畴中的一个 monoid

我们引用这句话来开场,所以把话题转到这个引言上面似乎是很合适的。可是才不会这样,我们不会讨论 Monad 、endofunctor 或者范畴论。这句引言不仅故弄玄虚而且华而不实。

我只希望通过我们的讨论,你不再害怕 Monad 这个术语或者这个概念了 —— 我曾经怕了很长一段时间 —— 并在看到该术语时知道它是什么。你可能,也只是可能,会正确地使用到它们。

类型

在函数式编程中有一个巨大的兴趣领域:类型论,本书基本上完全远离了该领域。我不会深入到类型论,坦白的说,我没有深入的能力,即使干了也吃力不讨好。

但是我要说,Monad 基本上是一个值类型。

数字 42 有一个值类型(number),它带有我们依赖的特征和功能。字符串 "42" 可能看起来很像,但是在编程里它有不同的用途。

在面向对象编程中,当你有一组数据(甚至是一个单独的离散值),并且想要给它绑上一些行为,那么你将创建一个对象或者类来表示 "type"。接着实例就成了该类型的一员。这种做法通常被称为 “数据结构”。

我将会非常宽泛的使用数据结构这个概念,而且我断定,当我们在编程中为一个特定的值定义一组行为以及约束条件,并且将这些特征与值一起绑定在一个单一抽象概念上时,我们可能会觉得很有用。这样,当我们在编程中使用一个或多个这种值的时候,它们的行为会自然的出现,并且会使它们更方便的工作。方便的是,对你的代码的读者来说,是更有描述性和声明性的。

Monad 是一种数据结构。是一种类型。它是一组使处理某个值变得可预测的特定行为。

回顾第 8 章,我们谈到了函子(functor):包括一个值和一个用来对构成函子的数据执行操作的类 map 实用函数。Monad 是一个包含一些额外行为的函子(functor)。

松散接口

实际上,Monad 并不是单一的数据类型,它更像是相关联的数据类型集合。它是一种根据不同值的需要而用不同方式实现的接口。每种实现都是一种不同类型的 Monad。

例如,你可能阅读 "Identity Monad"、"IO Monad"、"Maybe Monad"、"Either Monad" 或其他形形色色的字眼。他们中的每一个都有基本的 Monad 行为定义,但是它根据每个不同类型的 Monad 用例来继承或者重写交互行为。

可是它不仅仅是一个接口,因为它不只是使对象成为 Monad 的某些 API 方法的实现。对这些方法的交互的保障是必须的,是 monadic 的。这些众所周知的常量对于使用 Monad 提高可读性是至关重要的;另外,它是一个特殊的数据结构,读者必须全部阅读才能明白。

事实上,这些 Monad 方法的名字和真实接口授权的方式甚至没有一个统一的标准;Monad 更像是一个松散接口。有些人称这些方法为 bind(..),有些称它为 chain(..),还有些称它为 flatMap(..),等等。

所以,Monad 是一个对象数据结构,并且有充足的方法(几乎任何名称或排序),至少满足了 Monad 定义的主要行为需求。每一种 Monad 都基于最少数量的方法来进行不同的扩展。但是,因为它们在行为上都有重叠,所以一起使用两种不同的 Monad 仍然是直截了当和可控的。

从某种意义上说,Monad 更像是接口。

Maybe

在函数式编程中,像 Maybe 这样涵盖 Monad 是很普遍的。事实上,Maybe Monad 是另外两个更简单的 Monad 的搭配:Just 和 Nothing。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxpxd.html