點燈坊

失くすものさえない今が強くなるチャンスよ

Sanctuary 初體驗

Sam Xiao's Avatar 2020-09-11

Sanctuary 為著名的 Functional Library,其比 Ramda 嚴格,也能在 Runtime 檢查型別,且完整支援 Fantasy Land 的 Algebraic Data Type,寫起來更有 Haskell 感覺。

Version

Sanctuary 3.1.0

Maybe

import { propEq } from 'ramda'
import { pipe, find } from 'sanctuary'

let data = [
  { title: 'FP in JavaScript', price: 100 },
  { title: 'Elm in Action', price: 200 },
  { title: 'Speaking JavaScript', price: 300 }
]

let f = s => pipe ([
  find (propEq ('title') (s))
])

f ('Speaking JavaScript') (data) // ?
f ('Elm') (data) // ?

第 2 行

import { pipe, find } from 'sanctuary'

不是使用 Ramda 的 find,而是使用 Sanctuary 的 find,因為回傳 Maybe。

第 10 行

let f = s => pipe ([
  find (propEq ('title') (s))
])

使用 pipe 組合 f

  • find (propEq ('title') (s)):尋找 titles 的 Maybe

find
Foldable f => (a -> Boolean) -> f a -> Maybe a
回傳第一個符合 predicate 的 element,但回傳Maybe

a -> Boolean:判斷條件的 predicate

f a:data 為 Foldable

Maybe a:將結果包進 Maybe 內回傳

overview000

若找得到資料則回傳 Just,若找不到則回傳 Nothing。

fromMaybe()

import { propEq, pluck } from 'ramda'
import { pipe, find, fromMaybe } from 'sanctuary'

let data = [
  { title: 'FP in JavaScript', price: 100 },
  { title: 'Elm in Action', price: 200 },
  { title: 'Speaking JavaScript', price: 300 }
]

let f = s => pipe ([
  find (propEq ('title') (s)),
  pluck ('price'),
  fromMaybe (0)
])

f ('Speaking JavaScript') (data) // ?
f ('Elm') (data) // ?

10 行

let f = s => pipe ([
  find (propEq ('title') (s)),
  pluck ('price'),
  fromMaybe (0)
])

使用 pipe 組合 f

  • find (propEq ('title') (s)):尋找 titles 的 Maybe
  • pluck ('price'):在 Maybe 內取得 price
  • fromMaybe(0):若為 Nothing 則回傳 0

fromMaybe
a -> Maybe a -> a
從 Maybe 取出內部值,並提供 Nothing 預設值

a:Nothing 的預設值

Maybe a:data 為 Maybe

a:回傳 Maybe 內部值

overview001

Conclusion

  • 理論上 Ramda 的 function 若可能回傳 undefined,則建議改用 Sanctuary 的 function 改回傳 Maybe

Reference

Sanctuary, find
Sanctuary, fromMaybe