IO
函子这个_value
属性他里面要去合并很多函数,所以他里面可能是不纯的 , 把这些不纯的操作延迟到了调用的时候,也就是我们通过IO
函子控制了副作用的在可控的范围内发生
实现 liunx 下 cat 命令
const fp = require('lodash/fp')// IO 函子class IO {constructor (fn) {this._value = https://www.huyubaike.com/biancheng/fn}static of (value) {return new IO(function () {return value})}map (fn) {// 把当前的value 和传入的fn 函数组合成一个新的函数return new IO(fp.flowRight(fn, this._value))}}let r = IO.of(process).map(x => x.execPath)function readFile (fileName) {return new IO(() => fs.readFileSync(fileName,'utf-8'))}function print (x) {return new IO(() => {console.log(x)return x})}let cat = fp.flowRight(print, readFile)console.log(cat('package.json')._value()._value())
此时IO
函子出现了嵌套的问题,导致调用嵌套函子中的方法就必须要要._value()._value()
这样来执了,嵌套了几层就需要几层调用FolktaleFolktale 是一个标准的函数式编程库,和
lodash
不同的是 , 他没有提供很多功能函数,只提供了一些函数式处理的操作,例如:compose、curry
等 , 一些函子 Task、Either、MayBe
等,Folktale中的
curry
与compose
的简单使用const { compose, curry } = require('folktale/core/lambda')const { toUpper, first } = require('lodash/fp')// 与lodash区别,第一个参数指明后面参数的个数let f = curry(2, (n1, n2) => n1 + n2)console.log(f(1, 2))// compose 就是函数组合 lodash 中的函数组合是 flowRightlet f2 = compose(toUpper, first)console.log(f2(['one', 'two']))
Folktale 中的 task 函子函子可以处理异步任务,在异步任务中会通往地狱之门的回调,而使用task
函子可以避免回调的嵌套 , 详细请看官方文档// Task 异步任务const { task } = require('folktale/concurrency/task')const { split, find } = require('lodash/fp')const fs = require('fs')function readFile (filename) {return task(resolver => {fs.readFile(filename, 'utf-8', (err, data) => {if (err) {resolver.reject(err)}resolver.resolve(data)})})}readFile('package.json').map(split('\n')).map(find(x => x.includes('version')))// 执行读取文件.run().listen({onRejected(err) {console.log(err)},onResolved(value) {console.log(value)}})
Pointed函子Pointed函子 是实现了of静态方法 , of 方法是为了避免使用new 来创建对象,更深层次含义是of方法把值放到上下文Context
(把值放到容器中,使用map
来处理值)class Container {constructor (value) {this._value = https://www.huyubaike.com/biancheng/value} static of () {return new Container(value)}map (fn) {return new Container(fn(this._value))}}
Monad函子解决函子嵌套的问题,Monad
函子是可以变扁的 Pointed
函子 IO(IO)
,一个函子如果具有join
和of
两个方法并遵循一些定律就是一个Monad
class IO {constructor (fn) {this._value = https://www.huyubaike.com/biancheng/fn}static of (value) {return new IO(function () {return value})}map (fn) {return new IO(fp.flowRight(fn, this._value))}join () {return this._value()}// 同时调用 join 和 mapflatMap (fn) {return this.map(fn).join()}}function readFile (fileName) {return new IO(() => fs.readFileSync(fileName,'utf-8'))}function print (x) {return new IO(() => {return x})}let r = readFile('package.json').flatMap(print).join()console.log(r)
当我们想要去调用一个方法,这个方法返回一值的时候我们去调用map
方法,当我们想要去调用一个方法,这个方法返回一个函子的时候我们去调用flatMap
方法原文地址:https://kspf.xyz/archives/17更多内容微信公众号搜索充饥的泡饭
小程序搜一搜开水泡饭的博客
推荐阅读
- Java函数式编程:一、函数式接口,lambda表达式和方法引用
- Vue3 SFC 和 TSX 方式调用子组件中的函数
- C++ 函数重载解析策略
- 原生JavaScript
- 钩子 【pytest官方文档】解读-插件开发之hooks 函数
- Java 最长公共前缀
- TCP和UDP的区别与联系以及网络字节序和主机字节序的转换函数实践
- Python函数-2V2
- MySQL 窗口函数
- JavaScript之无题之让人烦躁的模块化