美文网首页
functional programming

functional programming

作者: 柒轩轩轩轩 | 来源:发表于2018-05-13 10:46 被阅读0次

    这篇文章总结于阮一峰老师的博客
    functional programming is the process of building software by composing pure functions, avoid shared state, mutable data and side-effects.

    特点

    1.函数是第一等公民

    指的是函数与其他数据类型一样,可以赋值给其他变量,也可以作为参数传入另一个函数,或者作为别的函数的返回值

    var print = function(i){ console.log(i);};
    [1,2,3].forEach(print);
    

    2. 只用expression,不用statement

    expression是一个单纯的运算过程,总是有返回值,statement是执行某种操作,没有返回值

    3.没有side effect

    所谓side effect,指的是函数内部和外部互动,产生运算以外的其他结果。
    没有side effect 意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值

    4. 不修改状态

    函数式编程使用参数保存状态

    5. 引用透明

    指的是函数的运行不依赖于外部变量或者状态,只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的

    范畴论

    In mathematics, a category is an algebraic structure that comprises "objects" that are linked by "arrows".
    我们可以把范畴想象成是一个容器,里面包括:
    值和值的变形关系也就是函数

    函数的合成和柯里化

    函数的合成

    如果一个值要经过多个函数,才能变成另一个值,就可以把所有中间步骤合并成一个函数

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

    柯里化

    f(x)和g(x) 合并成 f(g(x)),有一个隐藏的前提,就是f和g都只能接受一个参数

    function add(x, y){
    return x+y;
    }
    add(1, 2) //3
    function addX(y){
      return function (x){
        return x + y;
      };
    }
    addX(2)(1) //3
    

    一般约定,函子的标志就是容器具有map方法,该方法将容器里面的每一个值,映射到另一个容器

    (new Functor(2).map(function(two){
    return two+2;
    });
    // Functor(4)
    (new Functor('flamethrowers')).map(function(s){
    return s.toUpperCase();
    });
    //Functor('FLAMETHROWERS')
    (new Functor('bomb')).map(_.concat(' away')).map(_.prop('length'));
    ### of方法
    函数式编程一般约定,函子有一个of方法,用来生成新的容器
    

    Functor.of = function(val){
    return new Functor(val);
    }

    Maybe函子

    函子接受各种函数,处理容器内部的值。这里就有一个问题,容器内部的值可能是一个null,而外部函数未必有处理控制的机制,如果传入空值,很可能就会出错

    class Maybe extends Functor {
      map(f) {
        return this.val ? Maybe.of(f(this.val)) : Maybe.of(null);
      }
    }
    

    Either函子

    Either函子内部有两个值:左值left和右值Right.
    正常情况下,使用右值,左值是右值不存在时使用的默认值

    class Either extends Functor {
      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);
    

    EIther函子的另一个用途是代替try...catch,使用左值表示错误

    ###ap函子
    函数里面包含的值,完全可能是函数
    

    class Ap extends Functor {
    ap(F) {
    return Ap.of(this.val(F.val));
    }
    }

    因此前面例子可以写成
    

    Ap.of(addTwo).ap(Functor.of(2))
    // Ap(4)

    function add(x) {
    return function (y) {
    return x + y;
    };
    }

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

    ### Monad函子
    Monad函子的作用是,总是返回一个单层的函子,它有一个flatMap方法,与map方法作用相同,唯一的区别是如果生成了一个嵌套函子,它会取出后者内部的值,保证返回的永远是一个单层的容器,不会出现嵌套的情况。
    ### IO操作
    Monad 函子的重要应用,就是实现 I/O (输入输出)操作。
    
    I/O 是不纯的操作,普通的函数式编程没法做,这时就需要把 IO 操作写成Monad函子,通过它来完成。
    

    var fs = require('fs');

    var readFile = function(filename) {
    return new IO(function() {
    return fs.readFileSync(filename, 'utf-8');
    });
    };

    var print = function(x) {
    return new IO(function() {
    console.log(x);
    return x;
    });
    }

    相关文章

      网友评论

          本文标题:functional programming

          本文链接:https://www.haomeiwen.com/subject/hkurrftx.html