什么时候使用Monad?
- 具有静态的IO方法和join方法的函子
- 当一个函数返回一个函子的时候,我们就要想到monad,monad可以帮我们解决函子嵌套的问题。
- 当我们想要返回一个函数,这个函数返回一个值,这个时候可以调用map 方法
- 当我们想要去合并一个函数,但是这个函数返回一个函子,这个时候我们要用flatMap 方法
- 示例: ```javascript const fp = require(‘lodash/fp’) const fs = require(‘fs’)
class IO { static of (value) { return new IO(() => { return value }) } constructor (fn) { this._value = fn }
map(fn) { return new IO(fp.flowRight(fn, this._value)) } }
//读取文件函数 let readFile = (filename) => { return new IO(() => { //同步获取文件 return fs.readFileSync(filename, ‘utf-8’) }) }
//打印函数 // x是上一步的IO函子 let print = (x) => { return new IO(()=> { console.log(x) return x }) }
// 组合函数,先读文件再打印 let cat = fp.flowRight(print, readFile) // 调用 // 拿到的结果是嵌套的IO函子 IO(IO(x)) let r = cat(‘package.json’) console.log(r) // IO { _value: [Function] } console.log(cat(‘package.json’)._value()) // IO { _value: [Function] } // IO { _value: [Function] } console.log(cat(‘package.json’)._value()._value()) // IO { _value: [Function] }
2. 实现一个Monad函子:```javascriptconst fp = require('lodash/fp')const fs = require('fs')class IO {static of (value) {return new IO(() => {return value})}constructor (fn) {this._value = fn}map(fn) {return new IO(fp.flowRight(fn, this._value))}join () {return this._value()}// 同时调用map和join方法flatMap (fn) {return this.map(fn).join()}}let readFile = (filename) => {return new IO(() => {return fs.readFileSync(filename, 'utf-8')})}let print = (x) => {return new IO(()=> {console.log(x)return x})}let r = readFile('package.json').flatMap(print).join()// 执行顺序/*** readFile读取了文件,然后返回了一个IO函子* 调用flatMap是用readFile返回的IO函子调用的* 并且传入了一个print函数参数* 调用flatMap的时候,内部先调用map,当前的print和this._value进行合并,合并之后返回了一个新的函子* (this._value就是readFile返回IO函子的函数:* () => {return fs.readFileSync(filename, 'utf-8')}* )* flatMap中的map函数执行完,print函数返回的一个IO函子,里面包裹的还是一个IO函子* 下面调用join函数,join函数就是调用返回的新函子内部的this._value()函数* 这个this._value就是之前print和this._value的组合函数,调用之后返回的就是print的返回结果* 所以flatMap执行完毕之后,返回的就是print函数返回的IO函子* */r = readFile('package.json')// 处理数据,直接在读取文件之后,使用map进行处理即可.map(fp.toUpper).flatMap(print).join()// 读完文件之后想要处理数据,怎么办?// 直接在读取文件之后调用map方法即可
