本文将介绍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);