函数式编程-函子
什么是函子Functor
容器:包含值和值的变形关系,这个变形关系就是函数
函子:一个特殊的容器,通过一个普通对象实现,该对象具有map方法,map方法可以运行一个函数对值进行处理。
所有的函子都有 map 对象
maybe 函子
优点:对外部空值做处理
缺点:只可以处理空值,但当处理多个 map 的时候,无法定位哪个 map 出现了空值
// 可能会是空值
class Maybe {
static of(value) {
// 初始化
return new Maybe(value);
}
constructor(value) {
this._value = value;
}
map(fn) {
return this.isNothing() ? Maybe.of(null) : Maybe.of(fn(this._value));
}
isNothing() {
return this._value === null || this._value === undefined;
}
}
const res = Maybe.of("hello world")
.map((a) => a.toUpperCase())
.map((b) => null)
.map((c) => c.split(" "));
console.log(res); //Maybe { _value: null }
Either 函子
两者中任何一个,类似于 if。。else。。
异常会让函数变得不纯,用 Either 可以进行异常处理
class Left {
static of(val) {
return new Left(val);
}
constructor(val) {
this._val = val;
}
map(fn) {
return this;
}
}
class Right {
static of(val) {
return new Right(val);
}
constructor(val) {
this._val = val;
}
map(fn) {
return Right.of(fn(this._val));
}
}
function parseJSON(str) {
try {
return Right.of(JSON.parse(str));
} catch (e) {
return Left.of({ error: e.message });
}
}
const str = '{name:"hello"}';
const r = parseJSON(str); // Left { _val: { error: 'Unexpected token n in JSON at position 1' } }
const str2 = '{"name":"hello"}';
const r2 = parseJSON(str2).map((item) => item.name.toUpperCase()); // Right { _val: 'HELLO' }
IO 函子
_value 是一个函数,这里把函数作为值来处理
可以把不纯的动作存储到_value 中,延迟执行这个不纯的操作(惰性执行)
把不纯的操作交给调用者处理。
const fp = require("lodash/fp");
class IO {
static of(val) {
return new IO(function() {
return val;
});
}
constructor(val) {
this._val = val;
}
map(fn) {
return new IO(fp.flowRight(fn, this._val));
}
}
const r = IO.of(process).map((p) => p.execPath);
// console.log(r)
console.log(r._val());
把不纯的操作延迟到调用的时候
folktale task 函子
folktale 与 lodash ramda 不同的是,只提供了函数式处理的操作,如:compose、curry 等,和其他的一些函子,如 Task、Either、Maybe 等
const { compose, curry } = require("folktale/core/lambda");
const { toUpper, first } = require("lodash/fp");
const f = curry(2, (x, y) => x + y); // 第一个参数:参数个数
console.log(f(1)(3)); // 4
console.log(f(1)()(3)); // 4
const f1 = compose(toUpper, first);
console.log(f1(["aaa", "bbb"]));
monad 函子
monad 函子是解决函子嵌套的问题,如:IO(IO(x))
一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个 monad