什么时候使用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函子:
```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))
}
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方法即可