// 柯里化
function getSum(x) {
return function (y) {
return x + y
}
}
console.log(getSum(5)(6));
console.log(getSum(9));
function getSum2(f, g) {
return function (x) {
return f(g(x))
}
}
var getSum3 = (f, g) => x => f(g(x))
var s = getSum2(x => x + 1, y => y * 2)(5)
var s1 = getSum3(x => x + 1, y => y * 2)(5)
console.log(s);
console.log(s1);
// 它的map方法接受函数f作为参数,然后返回一个新的函子,里面包含的值是被f处理过的(f(this.val))。of方法:函数式编程一般约定,函子有一个of方法,用来生成新的容器。
class Functor {
constructor(val) {
this.val = val
}
map(f) {
return this.val ? Functor.of(f(this.val)) : Functor.of(null)
}
}
Functor.of = function (val) {
return new Functor(val)
}
// console.log(new Functor(2).map(x=>x+2).val);
var fff = Functor.of(null).map(function (s) {
return s.toUpperCase()
})
// console.log(fff);
// Either 函子内部有两个值:左值(Left)和右值(Right)。右值是正常情况下使用的值,左值是右值不存在时使用的默认值。
class Either extends Functor{
constructor(left,right){
super()
this.left = left;
this.right = right;
}
map(f){
return this.right ? Either.of(this.left,f(this.right)) :
Either.of(f(this.left),this.right)
}
}
Either.of = function(left,right){
return new Either(left,right)
}
var addOne = function(x){
return x + 1
}
Either.of(5,6).map(addOne)
Either.of(1,null).map(addOne)
// 上面代码中,如果右值有值,就使用右值,否则使用左值。通过这种方式,Either 函子表达了条件运算。
// Either 函子的常见用途是提供默认值。下面是一个例子。
// Either.of({address:'xxx'},currentUser.address).map(updateField)
// 上面代码中,如果用户没有提供地址,Either 函子就会使用左值的默认地址。
// Either函子的另一个用途是代替try...catch,使用左值表示错误
function parseJSON(json){
try{
return Either.of(null,JSON.parse(json))
} catch(e){
// } catch(e:Error){
return Either.of(e,null)
}
}
// 上面代码中,左值为空,就表示没有出错,否则左值会包含一个错误对象e。一般来说,所有可能出错的运算,都可以返回一个 Either 函子。
class Ap extends Functor {
ap(F) {
return Ap.of(this.val(F.val))
}
}
Ap.of = function (val) {
return new Ap(val)
}
function addTwo(x) {
return x + 2
}
console.log(Ap.of(addTwo).ap(Functor.of(2)));
// 函子接受各种函数,处理容器内部的值。这里就有一个问题,容器内部的值可能是一个空值(比如null),而外部函数未必有处理空值的机制,如果传入空值,很可能就会出错。
class Maybe extends Functor {
map(f) {
return this.val ? Maybe.of(f(this.val)) : Maybe.of(null)
}
}
// ap函子:函子里面包含的值,完全可能是函数。我们可以想象这样一种情况,一个函子的值是数值,另一个函子的值是函数。
// 链式应用
function add(x) {
return function (y) {
return function (z) {
return x + y + z
}
}
}
var bbb = Ap.of(add).ap(Maybe.of(2)).ap(Maybe.of(3)).ap(Maybe.of(4))
console.log(bbb);
// Monad函子
// 函子是一个容器,可以包含任何值。函子之中再包含一个函子,也是完全合法的。但是,这样就会出现多层嵌套的函子。
// Monad 函子的作用是,总是返回一个单层的函子。它有一个flatMap方法,与map方法作用相同,唯一的区别是如果生成了一个嵌套函子,它会取出后者内部的值,保证返回的永远是一个单层的容器,不会出现嵌套的情况。
Maybe.of(
Maybe.of(
Maybe.of({
name:'plus',
number:88888888
})
)
)
class Monad extends Functor{
join(){
return this.val
}
flatMap(f){
return this.map(f).join()
}
}