跳到主要内容

函子与提升

函子怎样变换容器里的值?​

  • 函子(Functor): 提供 map,把普通函数作用于内部值,并保留外层结构;
  • 形式: (A -> B) -> F<A> -> F<B>;

函子必须满足哪些定律?​

  • 恒等律: fa.map(x => x) 等价于 fa;
  • 复合律: fa.map(x => g(f(x))) 等价于 fa.map(f).map(g);
Some(1).map((x) => x); // Some(1)

const f = (x) => x + 1;
const g = (x) => x * 2;
Some(1).map((x) => g(f(x))); // Some(4)
Some(1).map(f).map(g); // Some(4)

Pointed Functor 多提供了什么?​

  • Pointed Functor: 提供 of,把任意单个普通值放入该函子;
  • 数组: ES2015 的 Array.of 提供这一入口;
Array.of(1); // [1]

提升怎样让普通值或函数进入上下文?​

  • 提升值: 用 of 把普通值放进函子;
  • 提升一元函数: 对函子使用后与 map 等价;
  • 提升多元函数: 先柯里化,再通过应用函子的 ap 逐个消费参数;
const liftA2 = (fn) => (fa, fb) => fa.map(fn).ap(fb);
const multiply = (a) => (b) => a * b;

liftA2(multiply)([1, 2], [3]); // [3, 6]
liftA2((a) => (b) => a + b)([1, 2], [30, 40]);
// [31, 41, 32, 42]

三个层级如何递进?​

Functor:map 普通函数
↓ 增加 of
Pointed Functor:把普通值放入上下文
↓ 配合 ap
Applicative Functor:应用上下文中的函数