实现代码如下:
class Maybe { constructor(value) { this.value = value } map(fn) { return this.value ? new Maybe(fn(this.value)) : null } } Maybe.of = value => new Maybe(value) Either 函子Either 函子 是为了对应 if...else... 的语法, 即非左即右。因此可以将之拆分为 Left 和 Right 两个函子, 它们的用法如下:
Left.of(1).map(r => r + 1) // Left {value: 1} Right.of(1).map(r => r + 1) // Right {value: 2}Left 函子实现代码如下:
class Left { constructor(value) { this.value = value } map(fn) { return this } } Left.of = value => new Left(value)Right 函子实现代码如下(其实就是上面的 Functor):
class Right { constructor(value) { this.value = value } map(fn) { return new Right(fn(this.value)) } } Right.of = value => new Right(value)具体 Either 函数只是对调用 Left 函子 或 Right 函子 作一层筛选, 其接收 f、g 两个函数以及一个函子(Left or Right)
var Either = function(f, g, functor) { switch(functor.constructor) { case 'Left': return f(functor.value) case 'Right': return g(functor.value) default: return f(functor.value) } }使用 demo:
Either((v) => console.log('left', v), (v) => console.log('def', v), left) // left 1 Either((v) => console.log('rigth', v), (v) => console.log('def', v), rigth) // rigth 2 Monad 函子函子会发生嵌套, 比如下面这样:
Functor.of(Functor.of(1)) // Functor { value: Functor { value: 1 } }Monad 函子 对外暴露了 join 和 flatmap 接口, 调用者从而可以扁平化嵌套的函子。
class Monad { constructor(value) { this.value = value } map(fn) { return new Monad(fn(this.value)) } join() { return this.value } flatmap(fn) { return this.map(fn).join() } } Monad.of = value => new Monad(value)使用方法:
// join Monad.of(Monad.of(1).join()) // Monad { value: 1 } Monad.of(Monad.of(1)).join() // Monad { value: 1 } // flatmap Monad.of(1).flatmap(r => r + 1) // 2Monad 函子可以运用在 I/O 这种不纯的操作上将之变为纯函数的操作,目前比较懵懂,日后补充。
后记 1: 数组字符串方法小结(是否对原值有影响) 不会对原数组有影响的方法 slice var test = [1, 2, 3] var result = test.slice(0, 1) console.log(test) // [1, 2, 3] console.log(result) // [1] concat var test = [1, 2, 3] var result = test.concat(4) console.log(test) // [1, 2, 3] console.log(result) // [1, 2, 3, 4] 对原数组有影响的方法 splice(这个需要特别记一下) var test = [1, 2, 3] var result = test.splice(0, 1) console.log(test) // [2, 3] console.log(result) // [1] sort var arr = [2, 1, 3, 4] arr.sort((r1, r2) => (r1 - r2)) console.log(arr) // [1, 2, 3, 4] reverse var test = [1, 2, 3] var result = test.reverse() console.log(test) // [3, 2, 1] console.log(result) // [3, 2, 1] push/pop/unshift/shift var test = [1, 2, 3] var result = test.push(4) console.log(test) // [1, 2, 3, 4] console.log(result) // 4 不会对原字符串造成影响的方法 substr/substring/slice // substr var test = 'abc' var result = test.substr(0, 1) console.log(test) // 'abc' console.log(result) // a // substring var test = 'abc' var result = test.substring(0, 1) console.log(test) // 'abc' console.log(result) // a // slice var test = 'abc' var result = test.slice(0, 1) console.log(test) // 'abc' console.log(result) // a 参考mostly-adequate-guide
JavaScript 专题之函数柯里化
函数式编程入门教程