chain和mcompose的例子:
import fs from 'fs'
import path from 'path'
import * as R from 'ramda'
const trace = R.curry((label, v) => {
console.log(label, v)
return v
})
const Maybe = function(x) {
this.__value = x
}
Maybe.of = function(x) {
return new Maybe(x);
}
Maybe.prototype.isNothing = function() {
return (this.__value === null) || (this.__value === undefined);
}
Maybe.prototype.map = function(fun) {
return this.isNothing() ? Maybe.of(null) : Maybe.of(fun(this.__value));
}
Maybe.prototype.join = function() {
return this.isNothing() ? this.of(null): this.__value
}
const join = function(mma) {
return mma.join()
}
const map = R.curry(function(f, any_functor_at_all) {
return any_functor_at_all.map(f);
});
let threeFn = v => Maybe.of(2).map(R.add(v))
let r = Maybe.of(3).map(threeFn).join().join() // 需要手动连续解两层
console.log(r)
// 使用chain
// 写法1
const chain = R.curry((f, m) => {
return R.compose(join, map(f))(m)
})
let res = chain(function(three) {
return Maybe.of(2).map(R.add(three));
}, Maybe.of(3))
console.log(res)
// 写法2
Maybe.prototype.chain = function(f) {
return R.compose(join, map(f))(this)
}
let sum = Maybe.of(3).chain( v => Maybe.of(2).chain(R.add(v)) )
console.log(sum)
// 进一步优化
// mcompose
const mcompose = function(f, g) {
return R.compose(chain(f), chain(g))
}
// 当有两个及以上chain时
const addFn = R.curry((n, v) => Maybe.of(n).map(R.add(v)))
let sum2 = R.compose(
chain(addFn(5)),
chain(addFn(2))
)
console.log(sum2(Maybe.of(3)))
// 使用mcompose
let res2 = mcompose(
addFn(5),
addFn(2)
)
console.log(res2(Maybe.of(3)))
- 每次使用map都会导致新增一个容器
- join用于手动解除容器包装
- 使用chain自动解包装
- mcompose 封装了compose和chain,语义清晰,使用简洁