iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Software Development

Should I use fp-ts系列 第 14

[Should I use fp-ts?] Day 14 - fp-ts: Option Do

  • 分享至 

  • xImage
  •  

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

O.Do

前幾天我們說到如何針對單個變數使用 Option 來進行操作,那需要操作多個變數的情況要如何處理?要如何暫時儲存變數?
這邊會使用到 Functoinal Programming 中著名的 Do notation,雖然在 javascript 當中的實作並不是那麼的優雅簡潔,但還是可以學習,首先我們看一下 O.Do 的建構子。

type DoType = O.Option<object>;
export const Do: DoType = O.of({});

沒錯,在 fp-tsDo 的實作是將使用到的變數儲存在一個 object 裡面,接著來看使用方法。

// use x=1, y=2 as example
const bindExample = (x: number, y: number) => pipe(
  O.Do, // { _tag: 'Some', value: {} }
  O.bind('x', () => O.of(x * 2 + 3)), // { _tag: 'Some', value: { x: 5 } }
  // bind's second fn can use the value from Do.
  O.bind('y', ({ x }) => O.of(y + x * 3)), // { _tag: 'Some', value: { x: 5, y: 17 } }
  O.map(({ x, y }) => x + y), // { _tag: 'Some', value: 22 }
  O.getOrElse(() => 0), // 22
);

首先使用 O.Do 來初始化 Do notation ({}) ,接著使用 O.bind 來 append 需要的屬性到 Do notation 之中,O.bind 首先接受 property 的名字(key),然後接受一個將要輸入的值,這邊需要注意的是,在使用 O.bind 的期間,我們可以從 callback function 中來使用目前 Do notation 中的屬性。
接著我們來嘗試 bind 的實作,首先從 type 開始。

type Bind =
  <N extends string, A, B>(name: Exclude<N, keyof A>, f: (a: A) => O.Option<B>)
    => (ma: O.Option<A>)
    => O.Option<{ readonly [K in keyof A | N]: K extends keyof A ? A[K] : B }>;

如果有些人對於 Typescript 不太熟悉的話可能會看不太懂,簡單來說就是傳入 (name, f) 前者是屬性名稱,後者則是運算出屬性結果的函式,接著接收(ma) 同時也是我們的 Do notation 本體,最終結果是新增 屬性 namema
接下來是實際的實作,會用到之前學習過的函式。

const bind: Bind = (name, f) => ma => pipe(
  ma,
  O.flatMap(a => pipe(
    f(a),
    O.map(b => Object.assign({}, a, { [name]: b }) as any),
  )),
);

藉於 ma: O.Do 本身就是 Option<A>,這邊需要使用 O.flatMap 來進行操作避免 nested Option,然後使用 f(a) 運算出要注入 Do 的函數,此時的型別會是 Option<B>,所以要使用 O.map 來進行運算,最後使用 Objectassign 來將兩者結合即可。

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

Reference

Option.ts | fp-ts


上一篇
[Should I use fp-ts?] Day 13 - fp-ts: Option fromNullable, fromPredicate
下一篇
[Should I use fp-ts?] Day 15 - fp-ts: Option bindTo
系列文
Should I use fp-ts25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言