JavaScript函數式編程之函子( 二 )

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中的currycompose的簡單使用
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),一個函子如果具有joinof兩個方法并遵循一些定律就是一個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更多內容微信公眾號搜索充饑的泡飯小程序搜一搜開水泡飯的博客

推薦閱讀