iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0
Software Development

Should I use fp-ts系列 第 7

[Should I use fp-ts?] Day 07 - fp-ts: Option 型別以及建構子

  • 分享至 

  • xImage
  •  

在本系列文中,所有的程式碼以及測試都可以在 should-i-use-fp-ts 找到,今日的範例放在 src/day-07 並且有習題和測試可以讓大家練習。

Option

今天終於開始要使用 fp-ts 中的 modules 了,選擇使用的 moduleOption,先來看 Option 中的基本型別。

import * as O from 'fp-ts/lib/Option';

type None = {
  readonly _tag: 'None';
}

type Some<A> = {
  readonly _tag: 'Some';
  readonly value: A;
}

type Option<A> = None | Some<A>;

這邊可以將 Option<A> 理解為一個箱子,我們會根據操作來決定箱子裡面是有(Some)還是沒有(None)所以沒有薛丁格的貓,接下來來看 Option 中的建構子。

const none: Option<never> = <const>({ _tag: 'None' });
const some = <A>(value: A): Some<A> => <const>({ _tag: 'Some', value });

const optionNone = O.none // { _tag: 'None' }
const option1 = O.some(1) // { _tag: 'Some', value: 1 }
const optionOf1 = O.of(1) // { _tag: 'Some', value: 1 }

Option 之中,所有不合法的元素都可以以 O.none 的形式來表現,這樣做可以統一對於不合法元素的處理(ex. string: "" => none, number: 0 => none, array: [] => none)。
這個特性有助於改寫 if...else 的判斷式,以下用 head(取 array 的首位)以及 inverse(倒數)為例。

/** Imperative */
const headI = <A>(xs: ReadonlyArray<A>) => {
  if (xs.length === 0) throw new Error('empty array');
  return xs[0];
};

const inverseI = (x: number) => {
  if (x === 0) throw new Error('cannot divide by zero');
  return 1 / x;
};

/** fp-ts */
type Head = <A>(xs: ReadonlyArray<A>) => O.Option<A>;
type Inverse = (x: number) => O.Option<number>;

const head: Head = xs => xs.length === 0 ? O.none : O.some(xs[0]);
const inverse: Inverse = x => x === 0 ? O.none : O.some(1 / x);

這邊將 Imperative 中的非法操作直接拋出 Error,而 fp-ts 這邊則是將非法操作統一設置為 O.none = { _tag: 'None' },這樣設計有助於後續操作失敗時可以產出統一的行為,這邊給出簡單的例子。

const getHeadI = (xs: ReadonlyArray<number>) => {
	try {
		return `result is ${headI(xs)}`;
	} catch {
		return 'no result';
	}
}

const getHeadO = (xs: ReadonlyArray<number>) => 
	head(xs) === O.none ? 'no result' : `result is ${headI(xs)}`;

可能會有人說,用三元運算子本身還是 if...else 阿,根本沒用老子不學了
這是由於今天還沒有講解 Option 中取用值以及運算的函式,明天學到 map, flatMap, match 三個函式之後這段操作可以完全不使用三元運算子,而且可以在一個 pipe 之中完成需求。

今天的主題在 should-i-use-fp-tssrc/day-07 並且有習題和測試可以讓大家練習。

Reference

Option.ts | fp-ts


上一篇
[Should I use fp-ts?] Day 06 - pipe and flow
下一篇
[Should I use fp-ts?] Day 08 - fp-ts: Option map
系列文
Should I use fp-ts25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言