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