iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
Software Development

Should I use fp-ts系列 第 10

[Should I use fp-ts?] Day 10 - fp-ts: Option getOrElse, getOrElseW

  • 分享至 

  • xImage
  •  

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

O.getOrElse

在前幾天我們已經學習到了如何使用 Option 改善業務邏輯的操作流程,但還沒將目標的數值提取出來。

const fp = (xs: ReadonlyArray<number>) => pipe( // use [1, 2, 3] as an example
  xs, // [1, 2, 3]
  head, // { _tag: 'Some', value: 1 }
  O.map(double), // { _tag: 'Some', value: 2 }
  O.flatMap(inverse), // { _tag: 'Some', value: 0.5 }
);

現在要實作 getOrElse 函式來做下列兩件事情:

  1. 如果結果是 Some 的話,傳回運算結果 (以上面為例: 0.5)
  2. 如果結果是 None 的話,傳回我們設定好的 onNone 結果 (ex. 0)
type GetOrElse = <A>(onNone: () => A) => (x: O.Option<A>) => A;
const getOrElse: GetOrElse = onNone => x => x._tag === 'None' ? onNone() : x.value;

getOrElse 需要先輸入 onNone 函式,來產出運算結果為 None 時的預設結果,現在用 getOrElse 來改寫上述例子。

const imperativeOrElse = (xs: ReadonlyArray<number>) => { // normal example
  try {
    return inverseI(double(headI(xs))); // get
  } catch {
    return 0; // orElse
  }
};

// use [1, 2, 3] as an example
const fpElse = (xs: ReadonlyArray<number>) => pipe( 
  xs, // [1, 2, 3]
  head, // { _tag: 'Some', value: 1 }
  O.map(double), // { _tag: 'Some', value: 2 }
  O.flatMap(inverse), // { _tag: 'Some', value: 0.5 }
  O.getOrElse(() => 0), // 0.5
);

O.getOrElseW

實作完 getOrElse 之後,就可以妥善處理各種 if...else 的情況了,但如果函式在 None 時,想要輸出不同於原輸出的型別呢?

const imperativeOrElseW = (xs: ReadonlyArray<number>) => {
  try {
    return inverseI(double(headI(xs))); // get
  } catch {
    return 'no value'; // orElseW
  }
};

沒錯,接下來要實作可以接受各種型別的 getOrElseW,只要處理 onNone 函式的輸出型別即可。

type GetOrElseW = <A, B>(onNone: () => B) => (x: O.Option<A>) => A | B;
const getOrElseW: GetOrElseW = onNone => x => x._tag === 'None' ? onNone() : x.value;
// use [0, 2, 3] as an example
const fpElseW = (xs: ReadonlyArray<number>) => pipe( 
  xs, // [0, 2, 3]
  head, // { _tag: 'None' }
  O.map(double), // { _tag: 'None' }
  O.flatMap(inverse), // { _tag: 'None' }
  getOrElseW(() => 'no value'), // 'no value'
);

今天的主題在 should-i-use-fp-ts src/day-10 有習題和測試可以練習,大家可以嘗試自己能不能寫出自己的 getOrElsegetOrElseW

Reference

Option.ts | fp-ts


上一篇
[Should I use fp-ts?] Day 09 - fp-ts: Option flatten, flatMap(chain)
下一篇
[Should I use fp-ts?] Day 11 - fp-ts: Option match, matchW
系列文
Should I use fp-ts25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言