跳到主要内容

折叠与遍历

Foldable 怎样把多个元素归约成一个值?​

  • Foldable: 提供 reduce,按顺序把累加器与每个元素结合;
  • 结果: 一个汇总值,不再保留原集合形状;
const sum = (xs) => xs.reduce((acc, value) => acc + value, 0);
sum([1, 2, 3]); // 6

Traversable 怎样把内外两层结构翻转?​

  • Traversable: 同时具备 Foldable 与 Functor 能力;
  • sequence / traverse: 把 F<G<A>> 变为 G<F<A>>;
  • 场景: 把一组 Promise 变成一个包含整组结果的 Promise,或把可选性移到集合外;
[Promise<A>, Promise<B>] -> Promise<[A, B]>
const promiseSequence = (promises) =>
promises.reduce(
(acc, promise) => acc.then((values) => promise.then((value) => [...values, value])),
Promise.resolve([]),
);

promiseSequence([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]).then(console.log); // [1, 2, 3]

sequence 与 traverse 有什么关系?​

  • sequence: 输入已经是“容器里的上下文值”,只翻转结构;
  • traverse: 先用函数把普通元素变成上下文值,再完成 sequence;
  • 直观关系: traverse(fn, xs) = sequence(xs.map(fn));

Foldable、Functor 与 Traversable 怎样分工?​

结构关注点
Functor保持外形并变换内部值
Foldable消解外形并汇总为一个结果
Traversable保持外形,同时把效果移到外层