飞雪团队

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 7120|回复: 0

图解 Monad

[复制链接]

5344

主题

5432

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
18354
发表于 2020-8-11 10:09:40 | 显示全部楼层 |阅读模式
函数式编程有一个重要概念,叫做Monad。
                                                                                                               
3e437e3c903a2b9075e950a6d2c4f60a.jpg

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

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

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

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

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

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

函数还可以依次处理数据集合的每个成员。
6.
1b4fbc2212afdbc8c6aedf38600b37f3.png

说完了函数,再来看第二个概念:数据类型(type)。
数据类型就是对值的一种封装,不仅包括值本身,还包括相关的属性和方法。上图就是2的封装,从此2就不是一个单纯的值,而是一种数据类型的实例,只能在数据类型的场景(context)中使用。
7.
d74deb7f76b89854f240427aeabab3ec.png

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

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

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

一个有趣的问题来了。如果我们把函数也封装成数据类型,会怎样?
上图就是把函数"(+3)"封装成一种数据类型。
11.
945ded28b65493ee8ba61a5d2aed683f.png

这时,就需要再定义一种新的运算。它不是值与值的运算,也不是值与数据类型的运算,而是数据类型与数据类型的运算。
上图中,两个数据类型进行运算。首先,取出它们各自的值,一个是函数,一个是数值;然后,使用函数处理数值;最后,将函数的返回结果再封装进数据类型。
12.
2e38c5fbd0519fb1914c586d0f252afd.png

函数可以返回值,当然也可以返回数据类型。
13.
4bbae0f2f7ee376a6c23dce4d885437d.png

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

这样做的好处是什么?
因为数据类型是带有运算方法的,如果每一步返回的都是数据类型的实例,我们就可以把它们连接起来。
15.
6f0cf2a38b10ffff941ede18b34a613e.png

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

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

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

putStrLn函数将文件内容输出。
19.
3d0a7d2dc5b00fb89169b19ed46c49fb.png

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

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|飞雪团队

GMT+8, 2024-11-24 06:07 , Processed in 0.076667 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表