iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0
export const textInputOf =
  ({ minLen, maxLen }: { minLen: number; maxLen: number }) =>
  (input: string) =>
    pipe(
      input,
      validateMinLen(minLen),
      Either.flatMap(validateMaxLen(maxLen)),
      Either.flatMap(validateWhiteList),
      // 以下兩行先忽略
      // Either.mapRight(ofValid),
      // Either.merge 
    )

回顧昨天的驗證程式,如果用 if else 寫會是這樣

const textInputOf = ({ minLen, maxLen }: { minLen: number; maxLen: number }) =>
(input: string): InvalidTextInput | ValidTextInput => {

	const either1 = validateMinLen(minLen)(input)
	
	if(either1._tag==='Right'){
		const input2 = either1.right
		const either2 = validateMaxLen(maxLen)(input2)
		if(either2._tag==='Right'){
			const input3 = either2.right
			const either3 = validateMaxLen(maxLen)(input3)
			if(either2._tag==='Right'){
				return either3
			}else{
				return either2
			}
		}else{
			return either2
		}
	}else{
		return either1
	}
}

mapRight, flatten, and flatMap

其中導致程式變成巢狀,而且一直重複出現的邏輯就是 Either flatMap,
它由 mapRight 和 flatten 組成

Either mapRight
想像 Either 是一個型別盒子,裡面可能有是 Right 也可能是 Left。
如果盒子裡面是 Right 就把右值取出放入一個能產生任意型別的 callback function,再把這個 function 的回傳值 Output2 包裝進 Either。
如果盒子裡面是 Left 就回傳 Either。
https://ithelp.ithome.com.tw/upload/images/20230923/201586156MSwEj3W0f.png

有時候剛好 callback function 的輸出也是一個 Either 盒子

https://ithelp.ithome.com.tw/upload/images/20230923/2015861550pvKbbzx8.png

這時候就要再加上一個 flatten 的操作

Either flatten
把重複兩層的其中一層盒子拆掉,保留值在同一層盒子裡
https://ithelp.ithome.com.tw/upload/images/20230923/20158615JcEhSm3WPb.png

把 mapRight和flatten 串起來就會變成這樣

https://ithelp.ithome.com.tw/upload/images/20230923/201586158AKAlg2bti.png

再把中間轉換的部份省略就得到了 flatMap

Effect flatMap
mapRight + flatten
https://ithelp.ithome.com.tw/upload/images/20230923/20158615piuVJOtp27.png

merge

在 Either 盒子中,Output 被包在 Right 裡面, Error 被包在 Left 裡面
當我們不需要區分 Left 或 Right 了,我們就可以把兩邊結果合併起來

https://ithelp.ithome.com.tw/upload/images/20230923/20158615RrbwI9lemQ.png

以 textInputOf 為例,經過 mapRight 處理後 Either 的左右值分別是 InvalidTextInput 和 ValidTextInput。這兩個型別都有 tag,可以合併成一個 sum type ,且合併後的 sum type 也是有意義的,因此我們就可以把 Either 盒子拆掉,把最終結果 InvalidTextInput | ValidTextInput 合在一起拿出來。

https://ithelp.ithome.com.tw/upload/images/20230923/20158615LHOFuSgXLW.png

把滑鼠移上去看型別在是一種相當好用的 debug 技巧
對型別有疑問? 滑鼠移上去就對了 !


最後要強調的是,Either 只是其中一種資料盒子,還有很多種盒子也有 map、flatMap 等概念。這些操作具體會做甚麼跟盒子類型有關。如果你想對資料型別盒子有更多瞭解,推薦參考 hanna 大大的文章


上一篇
D07 - 軌道導向設計
下一篇
D09 - 開始元件測試
系列文
從 Next.js 開始的 Functional Programming 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言