不完整解释 Monad 有什么用

栏目: 编程语言 · 发布时间: 5年前

内容简介:【预警】这篇文章没有详细解释 Monad,我承诺我会抽空写。关于我为什么自己打脸回来写文章,不想解释太多。只想说掘金真香。本打算这周末写文章解释下 Monad 的,但是最近比较忙,还是再拖一会。

【预警】这篇文章没有详细解释 Monad,我承诺我会抽空写。

关于我为什么自己打脸回来写文章,不想解释太多。只想说掘金真香。

本打算这周末写文章解释下 Monad 的,但是最近比较忙,还是再拖一会。

新工作挑战比较大。第一次遇到这么复杂的业务和开发流程,一开始适应的不是很好。开会全程懵逼,不知道别人在讲什么。最近主要精力还是要花在熟悉业务和新的工作环境,学习分享上会缓一缓。

先简单介绍一下 Monad 的用处预热一下吧。可能看完这篇你不会全懂,那是因为我没仔细解释,留待下次吧,抱歉了。这里要展示的代码主体部分是我的练习改写,后半部辅助函数和示例是我模仿改写的。

function IO(effectFn) {
  const __val = effectFn
  const map = fn => IO(() => fn(__val()))
  const performUnsafeIO = __val
  const chain = fn => IO(() => fn(__val()).performUnsafeIO())
  return Object.freeze({
    map,
    chain,
    performUnsafeIO,
  })
}

const curry = fn => (...args) =>
  args.length >= fn.length ? fn(...args) : curry(fn.bind(undefined, ...args))

const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))

const map = curry((fn, monad) => monad.map(fn))

const chain = curry((fn, monad) => monad.chain(fn))

const setStyle = curry((sel, props) => IO(() => $(sel).css(props)))

const getItem = key => IO(() => localStorage.getItem(key))

const applyPreferences = compose(
  chain(setStyle('#main')),
  map(JSON.parse),
  getItem
)

applyPreferences('preferences').performUnsafeIO()
复制代码

这个 IO Monad 在一些 ADT 库里面也叫 Effect,它是来处理应用中的作用的。先看示例部分。这个应用的主要功能就是从 localStorage 读取用户的样式偏好,读到之后再改掉页面对应的样式。这个简单例子涉及到两个作用(effects),注意作用和副作用(side effects)是两个不同的概念。这两个作用是读取数据库和改变 DOM 节点样式属性。函数式编程的一个主要挑战就是把计算和作用分离开来,计算的过程中不能产生作用。

回到代码看是怎样做到的。首先 getItem 函数把根据传入的 key 读取 localStorage 的行为扔进了 IO 函数。IO 函数把这个会产生作用的里层函数存在闭包里,并没有立即执行。map 的作用就是,先执行传进 IO 的函数,再把计算结果传进 map 自身接受的回调函数。但是请注意,map 并没有立即执行会产生作用的函数,它只是声明了行为。接着,到了最难理解的 chain 函数(如果你理解了 chain 在干什么,你就完全理解 Monad 了)。chain 接受的回调函数自身也会返回一个 IO,这个时候就不能直接把回调函数执行的结果扔回给 IO 了,不然就是 IO 嵌套 IO,没办法 map 了。所以先把里层 IO 的作用函数执行一遍,再把结果塞回 IO。同样,这里只是声明行为,没有真的执行。

程序运行到 applyPreferences("preferences") 的时候,就把应用功能全部描述完了,但只是定义了每一步的计算,还没开始执行指令。到最后一部 performUnsafeIO 的时候,奇迹才会发生,作用才会释放。再回过头看整个程序,是不是觉得很干净?不管你有没感受到,反正我感受到了……

你可能会问:谁 TM 这样子写代码找抽啊!!!

其实,RxJS 的原理差不多就是这样的。Observable 就是个 IO Monad。RxJS 里面声明的计算,都是惰性的,只有在最后 subscribe 的时候,计算才会被触发,作用才会被释放。

线上 Demo 戳这里。

这篇文章也发表在我的中文博客上Lambda Academy


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

scikit learn机器学习

scikit learn机器学习

黄永昌 / 机械工业出版社 / 2018-3-1 / CNY 59.00

本书通过通俗易懂的语言、丰富的图示和生动的实例,拨开了笼罩在机器学习上方复杂的数学“乌云”,让读者以较低的代价和门槛轻松入门机器学习。本书共分为11章,主要介绍了在Python环境下学习scikit-learn机器学习框架的相关知识。本书涵盖的主要内容有机器学习概述、Python机器学习软件包、机器学习理论基础、k-近邻算法、线性回归算法、逻辑回归算法、决策树、支持向量机、朴素贝叶斯算法、PCA ......一起来看看 《scikit learn机器学习》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

html转js在线工具
html转js在线工具

html转js在线工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具