函数式编程学习总结

178 阅读3分钟

函数式编程学习总结

什么是函数式编程?

函数编程是一种编程风格。把过程抽象成函数,让数据在纯函数间流动。

纯函数

纯函数的意思是函数内部不接受任何外界的影响,相同的参数得到的输出总是相同。
纯函数的好处
可缓存性
    纯函数总是根据输入来确定输出的值,这样就可把一些需要重复使用的输入缓存下来。
利于测试
    因为纯函数不依赖外界,在测试时就不用准备运行时环境,只需要根据输入断言输出。

函数柯里化

概念:
    只传递给函数的一部分参数来调用它,返回一个函数来处理剩余的参数。
柯里化的好处:
    尽可能的函数化。通过传递部分参数的形式得到一个新的函数。这样像是对部分参数做了一个缓存。
    function add(x){
        return function(y){
            return x + y;
        }
    }
    let addOne = add(1); //function
    addOne(2); //1+2

组合(compose)

组合就是像管道一样把不同的函数联系起来,数据在其中流动。
好处:
    组合的代码更有可读性。如f(g(h(x)))这样的嵌套函数,把这种嵌套过程进行封装。
    就需要写compose(f,g,h)这样的代码。

容器

容器有两样东西:值,函数。容器的作用就是把外界隔开,只能通过指定的接口才能操作。

函子(functor)

定义:functor是实现了map函数并遵守一些特定规则的容器类型。
就是说函子的标志就是容器具有map方法,map将容器里的所有值映射到另一个容器。
函子就是函数式编程的基本单位,运算不同,衍生了不同类型的函子。
    Function (value){
        this.value = valuse;
    }
    Function.prototype.map = function(f){
        return new Function(f(this.value);
    }
Maybe函子
Maybe函子用于处理空值检查。它的map方法的实现就是:
    Maybe.prototype.map = function(f){
        return this.value ?  Maybe.of(null):Maybe.of(f(this.value);
    }
Either函子
Either函子就是处理try-catch和if-else 这样的问题。
有Leftright两个子类。使来Left表示错误和不为真的情况。
    Left.prototype.map = function(x){
        return this;
    }
    Right.prototype.map = function(f){
        return Right.of(f(this.value);
    }
    
//LeftRight的区别在于,Left的map方法只是返回这个容器,不做任何事情。这样就可以用Left来传递错误消息。
    Left可以让调用链中任意一环的错误立刻返回到调用链的尾部,这给我们错误处理带来了很大的方便,再也不用一层又一层的 try/catch。
Monad函子
Monad函子就是用来处理函子嵌套。它的作用就是返回一个单层的函子。
函子是一个容器,它的值可以是任意类型。也就是说函子的值可以是另一个函子。
当函子出现嵌套时,就需要使用this.value().this.value()方式来取值,这时就是需要Monad函子。

其内部实现:
    Monad.prototype.join(){
        return this.value;
    }
    //当f是一个函子时,map就会生成一个嵌套的函子。
    用join方法去掉外壳,保证返回的是一个单层的函子。
    Monad.protype.chain(f){
        return this.map(f).join();
    }
ap函子
ap就是这样一种函数,能够把一functor的函数值应用到另一个 functor 的值上。
    function addTwo(x) {
        return x + 2;
    }

    const A = Functor.of(2);
    const B = Ap.of(addTwo)
    
    Ap.ap = function (otherFunctor){
        return Ap.of(this.value(otherFunctor.value)
    }
    
    Ap.of(addTwo).ap(Functor.of(2))
IO
    var getFromStorage = function(key) {
        return function() {
            return localStorage[key];
        }
    }