點燈坊

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

使用 lift 提升 Unary Function

Sam Xiao's Avatar 2021-07-04

一般 Unary Function 並無法處理 Maybe、Either 或 Future,但只要透過 lift 提升後就可處理。

Version

Ramda 0.27.1

Primitive

import { negate } from 'ramda'
import { Just } from 'sanctuary'

negate (1) // ?
negate (Just (1)) // ?

negate 可處理 Number 為負值,但卻無法處理 Maybe Number 相加,因為 negate 無法處理 monadic type。

unary001

Maybe

Just

import { lift, negate } from 'ramda'
import { Just } from 'sanctuary'

let data = Just (1)

lift (negate) (data) // ?

negate 使用 lift 提升後就能接受 Maybe。

lift
(*… → *) → ([*]… → [*])
將一般 function 提升能處理 Apply 的 function

(*… → *):傳入一般 function

([*]… → [*]):回傳能處理 Apply 的 function

unary002

Nothing

import { lift, negate } from 'ramda'
import { Nothing } from 'sanctuary'

let data = Nothing

lift (negate) (data) // ?

data 為 Nothing,則 lift (negate) 也會回傳 Nothing。

unary003

Either

import { lift, negate } from 'ramda'
import { Right } from 'sanctuary'

let data = Right (1)

lift (negate) (data) // ?

negate 使用 lift 提升後也能接受 Either。

unary004

Left

import { lift, negate } from 'ramda'
import { Left } from 'sanctuary'

let data = Left (1)

lift (negate) (data) // ?

data 為 Left,則 lift (negate) 也能回傳 Left。

unary005

Future

Resolved

import { resolve, fork } from 'fluture'
import { pipe, lift, negate } from 'ramda'
import { error, log } from 'wink-fp'

let data = resolve (1)

pipe (
  lift (negate), 
  fork (error) (log)
) (data) 

negate 使用 lift 提升後也能接受 Future。

unary006

Rejected

import { reject, fork } from 'fluture'
import { pipe, lift, negate } from 'ramda'
import { error, log } from 'wink-fp'

let data = reject (1)

pipe (
  lift (negate), 
  fork (error) (log)
) (data) 

data 為 Rejected,則 lift (negate) 也能回傳 Rejected。

unary007

Why ?

看到這裡可能會覺得很神奇,為什麼 negate 這種一般 function 經過 lift 提升後就可以使用 Maybe、Either 與 Future 呢 ?

lift 原意是將普通 function 提升成能處理 Apply 的 function,它在內部會呼叫 Apply 的 ap,因此一般 function 得以在 Apply 內運算。

unary000

別忘了 Monad 必須符合 Functor、Apply、Applicative 所有特性,也就是 Monad 就是 Apply,它必須提供 ap,因此可被 lift 所提升的 function 能呼叫使用。

Conclusion

  • 不用擔心原本寫的 function 無法處理 Maybe、Either 與 Future 而重寫,只要使用 lift 加以提升後就可繼續使用 monadic type
  • 由於 Monad 就是 Apply,因此經過 lift 提升的 function 也適用於 Monad

Reference

Ramda, lift
stackoverflow, Can’t wrap my head around “lift” in Ramda.js