Skip to content

Latest commit

 

History

History
255 lines (225 loc) · 5.31 KB

基础.md

File metadata and controls

255 lines (225 loc) · 5.31 KB

基础

函数式编程是一种编程范式(可以理解为一种软件架构的思维模式)

1.理念

1.1 常见的编程范式

  • 面向对象编程:基于类、对象与方法的设计模式,拥有三个基础概念: 封装性、继承性、多态性
  • 命令式编程(过程化编程):更关心解决问题的步骤,一步步以语言的形式告诉计算机做什么
  • 事件驱动编程:事件订阅与触发,被广泛用于 GUI 的编程设计中
  • 函数式编程:函数是第一等公民,强调将计算过程分解成可复用的函数

1.2 函数式编程的理念

  • 纯函数:是函数式编程的基础
    • 优势
      • 完全独立,与外部解耦
      • 高度可复用
      • 可测试性
    • 条件
      • 不修改参数
      • 引用透明
      • 无副作用
  • 函数复合:将多个函数进行组合后调用
    • 扁平化嵌套:避免嵌套地狱 f(g(k(x))) 变为 xxx(f, g, k)(x)
    • 结果传递:const pipe = (...fs) => p => fs.reduce((v, f) => f(v), p)
  • 数据不可变性:这是一种数据理念,也是函数式编程中的核心理念之一
    • 核心:一个对象再被创建后便不会再被修改。当需要改变值时,是返回一个全新的对象,而不是直接在原对象上修改;
    • 目的:保证数据的稳定性,有效提高可控性与稳定性
    • immutable.jstrie数据结构:
      • 结构共享:可以共用不可变对象的内存引用地址,减少内存占用,提高数据操作性能;

1.3 高阶函数

以函数为参数,返回一个新的增强函数

  • 隔离抽象
  • 函数组合
  • 函数增强

1.4 函数式编程的好处

  • 复用性强
  • 无副作用
  • 可缓存
  • 可移植性
  • 可测试性

2.组成

范畴或容器(集合) = 值 + 变形关系(函数)

// 范畴:Category
// 值:this.val
// 变形关系:addOne
class Category {
  constructor(val) { 
    this.val = val; 
  }
  addOne(x) {
    return x + 1;
  }
}

3.基本运算

  • 柯里化:多参数函数编程单参数函数
  • 合成:合成多个函数
    • 必须单参数
    • 必须纯函数

3.1 合成

var compose = function (f, g) {
  return function (x) {
    return f(g(x))
  }
}

3.2 柯里化

// 柯里化之前
function add(x, y) {
  return x + y;
}

add(1, 2) // 3

// 柯里化之后
function addX(y) {
  return function (x) {
    return x + y;
  };
}

addX(2)(1) // 3

4.函子

作用于每一个值,将一个范畴转变成另一个范畴(学习函数式编程,实际上就是学习函子的各种运算)

class Functor {
  constructor(val) { 
    this.val = val; 
  }
  map(f) {
    return new Functor(f(this.val));
  }
}

5.of 方法

生成新的容器

class Functor {
  constructor(val) { 
    this.val = val; 
  }
  map(f) {
    return Functor.of(f(this.val));
  }
}
Functor.of = function(val) {
  return new Functor(val);
}

Functor.of(2).map(function (two) {
  return two + 2;
});
// Functor(4)

6.Maybe 函子

处理空值

class Maybe {
  constructor(val) { 
    this.val = val;
  }
  map(f) {
    return this.val ? Maybe.of(f(this.val)) : Maybe.of(null);
  }
}
Maybe.of = function(val) {
  return new Maybe(val);
}

Maybe.of(null).map(function (s) {
  return s.toUpperCase();
});
// Maybe(null)

7.Either 函子

处理默认值,类似if...else...

class Either {
  constructor(left, right) {
    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(5, 7);

Either.of(1, null).map(addOne);
// Either(2, null);

8.ap 函子

处理值为函数,ap方法的参数不是函数,而是另一个函子

class Maybe {
  constructor(val) { 
    this.val = val;
  }
  map(f) {
    return this.val ? Maybe.of(f(this.val)) : Maybe.of(null);
  }
}
Maybe.of = function(val) {
  return new Maybe(val);
}

class Ap {
  constructor(val) { 
    this.val = val;
  }
  ap(F) {
    return Ap.of(this.val(F.val));
  }
}
Ap.of = function (val) {
  return new Ap(val);
};

function add(x) {
  return function (y) {
    return x + y;
  };
}
Ap.of(add).ap(Maybe.of(2)).ap(Maybe.of(3));
// Ap(5)

Ap.of(add(2)).ap(Maybe.of(3));
// Ap(5)

9.Monad 函子

总是返回一个单层的函子

class Monad {
  constructor(val) { 
    this.val = val;
  }
  join() {
    return this.val;
  }
  flatMap(f) {
    return this.map(f).join();
  }
  map(f) {
    return new Monad(f(this.val));
  }
}
var readFile = function() {
  return new Monad(function() {
    console.log('readFile')
  });
}

var print = function(read) {
  return new Monad(function() {
    read()
    console.log('print')
  });
}

var t = readFile().flatMap(print)
t.val()

参考