fp-ts函数式编程 - option, map, flatten & chain

第一篇之后,本文将介绍fp-ts中的option,map,flatten与chain。

option
作为一个容器,其所包含的内容可以为空(undefined),配合pipe使用可以提供安全的数据操作。如果遇到数据为空,则pipe后续方法不执行。代码示例如下:

import { pipe } from "fp-ts/lib/function";
import * as O from "fp-ts/lib/Option";
import * as A from "fp-ts/lib/Array";

const arr: number[] = [1];
const safeFirstElement: O.Option<number> = A.head(arr);

const firstElementDouble = pipe(
  safeFirstElement,
  O.map(value => value * 2)
);

console.log(firstElementDouble);

上述代码示例中,如果arr为空,则A.head结果为空,safeFirstElement为空,O.map不会执行。如果aarr不为空,O.map则正常执行。

map
与js原生方法中的map类似,将一个数据结构映射为另一个数据结构。代码示例可参照前面option的示例。

fp-ts/lib/Array/flatten
字面意思为数组的扁平化,很好理解,就是将多维对象降维。代码示例如下:

import { flatten } from 'fp-ts/lib/Array'

const twoDimensionArr: number[][] = [[1,2,3], [4,5,6]];
const result = flatten(twoDimensionArr);
//[ 1, 2, 3, 4, 5, 6 ]

再来看fp-ts/lib/Option下的chain和flatten方法
chain的作用是将一串计算方法组合在一起,将前一个方法的计算结果传递给后一个方法。 flatten则是将option对象转换为普通的对象。

const flattenTest = pipe(
    Option.some(2),
    Option.fromNullable,
    Option.flatten 
  );

  console.log(flattenTest);

以上代码打印出的是{ _tag: 'Some', value: 2 }
如果去掉Option.flatten,打印出的则是{ _tag: 'Some', value: { _tag: 'Some', value: 2 } }

接下来看一个更完整的例子

import * as Option from "fp-ts/lib/Option";
import { pipe } from "fp-ts/lib/function";

const doubleIfEvenElseNone = (n: number) => n % 2 === 0
  ? Option.some(2 * n)
  : Option.none

const increaseIfEven = (n: number) => n % 2 === 0
  ? Option.some(n+1)
  : Option.some(n)

const optionEven = Option.some(2);
const optionOdd = Option.some(3);

Option.chain(doubleIfEvenElseNone)(optionEven) // Option.some(4)

const odd = pipe(
  optionOdd,
  Option.chain(doubleIfEvenElseNone)
) // Option.none

console.log(odd);

const even = pipe(
    optionEven,
    Option.map(doubleIfEvenElseNone), // Option.some(Option.some(4))
  );
  console.log(even);

const evenFlattened = pipe(
    optionEven,
    Option.map(doubleIfEvenElseNone), // Option.some(Option.some(4))
    Option.flatten // Option.some(4)
  );

  console.log(evenFlattened);

const even2 = pipe(
    optionEven,
    Option.chain(doubleIfEvenElseNone),
    Option.chain(increaseIfEven)
  ) // Option.none

  console.log(even2);

参考:
https://rlee.dev/practical-guide-to-fp-ts-part-2
https://dev.to/ryanleecode/practical-guide-to-fp-ts-option-map-flatten-chain-6d5
https://githubmemory.com/repo/inato/fp-ts-cheatsheet

posted @ 2021-10-12 22:20  老胡Andy  阅读(1099)  评论(0编辑  收藏  举报