图解 Monad

简介:

函数式编程有一个重要概念,叫做Monad

网上有很多解释(这里这里),但都很抽象,不容易看懂。我尝试了好多次,还是不明白Monad到底是什么。

昨天,我读到了Aditya Bhargava的文章,他画了很多图。我想了半天,终于恍然大悟。下面,我就用这些图来解释Monad。

1.

软件最基本的数据,就是各种值(value)。

2.

处理值的一系列操作,可以封装成函数。输入一个值,会得到另一个值。上图的"(+3)"就是一个函数,对输入的值加上3,再输出。

3.

函数很像漏斗,上面进入一个值,下面出来一个值。

4.

函数可以连接起来使用,一个函数接着另一个函数。

5.

函数还可以依次处理数据集合的每个成员。

6.

说完了函数,再来看第二个概念:数据类型(type)。

数据类型就是对值的一种封装,不仅包括值本身,还包括相关的属性和方法。上图就是2的封装,从此2就不是一个单纯的值,而是一种数据类型的实例,只能在数据类型的场景(context)中使用。

7.

2变成数据类型以后,原来的函数就不能用了。因为"(+3)"这个函数是处理值的(简称"值函数"),而不是处理数据类型的。

8.

我们需要重新定义一种运算。它接受"值函数"和数据类型的实例作为输入参数,使用"值函数"处理后,再输出数据类型的另一个实例。上图的fmap就代表了这种运算。

9.

fmap的内部,实际上是这样:打开封装的数据类型,取出值,用值函数处理以后,再封装回数据类型。

10.

一个有趣的问题来了。如果我们把函数也封装成数据类型,会怎样?

上图就是把函数"(+3)"封装成一种数据类型。

11.

这时,就需要再定义一种新的运算。它不是值与值的运算,也不是值与数据类型的运算,而是数据类型与数据类型的运算。

上图中,两个数据类型进行运算。首先,取出它们各自的值,一个是函数,一个是数值;然后,使用函数处理数值;最后,将函数的返回结果再封装进数据类型。

12.

函数可以返回值,当然也可以返回数据类型。

13.

我们需要的是这样一种函数:它的输入和输出都是数据类型。

14.

这样做的好处是什么?

因为数据类型是带有运算方法的,如果每一步返回的都是数据类型的实例,我们就可以把它们连接起来。

15.

来看一个实例,系统的I/O提供了用户的输入。

16.

getLine函数可以将用户的输入处理成一个字符串类型(STR)的实例。

17.

readfile函数接受STR实例当作文件名,返回一个文件类型的实例。

18.

putStrLn函数将文件内容输出。

19.

所有这些运算连起来,就叫做Monad。

简单说,Monad就是一种设计模式,表示将一个运算过程,通过函数拆解成互相连接的多个步骤。你只要提供下一步运算所需的函数,整个运算就会自动进行下去。


目录
相关文章
|
6月前
|
存储 搜索推荐 算法
Java数组全套深入探究——进阶知识阶段2、冒泡排序
Java数组全套深入探究——进阶知识阶段2、冒泡排序
81 0
|
C语言
数据结构pta训练题-编程题1(1)
数据结构pta训练题-编程题
142 0
|
5月前
|
机器学习/深度学习 算法 C语言
详细介绍递归算法在 C 语言中的应用,包括递归的基本概念、特点、实现方法以及实际应用案例
【6月更文挑战第15天】递归算法在C语言中是强大力量的体现,通过函数调用自身解决复杂问题。递归涉及基本概念如自调用、终止条件及栈空间管理。在C中实现递归需定义递归函数,分解问题并设定停止条件。阶乘和斐波那契数列是经典应用示例,展示了递归的优雅与效率。然而,递归可能导致栈溢出,需注意优化。学习递归深化了对“分而治之”策略的理解。**
108 7
|
算法 数据安全/隐私保护
数据结构Pta训练题-编程2(2)
数据结构Pta训练题-编程
39 0
|
存储 算法
数据结构pta训练题-编程题1(2)
数据结构pta训练题-编程题
293 0
|
程序员 C语言
初阶函数经典例题(2)
初阶函数经典例题(2)
|
6月前
|
算法 Java 程序员
Java数组全套深入探究——进阶知识阶段4、一维数组练习题
Java数组全套深入探究——进阶知识阶段4、一维数组练习题
57 0
Java数组全套深入探究——进阶知识阶段4、一维数组练习题
|
6月前
|
搜索推荐 Java 程序员
Java数组全套深入探究——进阶知识阶段1、选择排序
Java数组全套深入探究——进阶知识阶段1、选择排序
53 0
数据结构Pta训练题-编程2(1)
数据结构Pta训练题-编程
57 0