问题:IO函子其实主要是一种过滤器的写法,又称为 “垃圾桶”,意思是将不纯的行为丢进垃圾桶,即IO函子
    我们可以看下这个案例

    1. /**
    2. * 如果组合函数返回的是函子,那么容易造成函子嵌套的问题
    3. */
    4. const fs = require("fs");
    5. const { flowRight } = require("lodash/fp");
    6. class IO {
    7. static of(value) {
    8. return new IO(value);
    9. }
    10. constructor(value) {
    11. this._value = value;
    12. }
    13. map(fn) {
    14. return new IO(flowRight(fn, this._value));
    15. }
    16. }
    17. // 读文件
    18. const readFile = (filename) => {
    19. return new IO(() => fs.readFileSync(filename, "utf-8"));
    20. };
    21. // 查看文件
    22. const print = (value) => {
    23. // console.log('value',value) // value IO { _value: [Function (anonymous)] }
    24. return new IO(() => value);
    25. };
    26. // readFile返回函子, print返回函子,IO(IO(X))
    27. /**
    28. * 1. 调用flowRight(print, readFile)时,组合函数从右到左执行,readFile 返回一个函子,print 接收 readFile 返回的函子
    29. * 2. print 执行 参数value是 readFile返回的函子,自身 retrun 一个函子
    30. * 3. flowRight最终返回的是一个函子里包含着函子,这是一种嵌套函子
    31. */
    32. const v = flowRight(print, readFile);
    33. // 嵌套多重函子,蹩脚的写法,IO函子的局限性,当出现多重函子时,可读性不高
    34. const r = v("package.json")._value()._value();
    35. console.log(r);

    得知 :

    1. 读文件和查看文件, 这两个函数是不纯的行为
    2. 为了解决不纯, 将这种行为丢进IO函子中, 通过函数包裹操作文件的逻辑传进去, 并且返回一个新的IO函子
    3. 将两个操作函数进行整合成一个组合函数
    4. 调用组合函数,率先执行readFile方法,那么会返回一个函子,这个函子会被print接送, 然而print也会返回一个函子,接收的参数又是一个函子
    5. 最后print将这个函子传递到IO函子中,并返回一个新的IO函子,得到的是一个函子嵌套函子

    问题显而易见:

    1. 函数嵌套函数,可以用函数组合来整合
    2. 函子嵌套函子,怎么解决?

    答复:

    1. 可以直接调用函子返回的_value方法,嵌套多少层,就调用多少层
    2. 使用monad函子,处理函子嵌套函子