點燈坊

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

使用 lift2 提升 Binary Function

Sam Xiao's Avatar 2021-06-26

一般我們所寫的 Function 都只能處理 ECMAScript 的原生 Type,而無法處理 Maybe、Either、Future 這類 Monadic Type,透過 lift2 可將普通 Binary Function 提升成能處理 Apply 的 Function。

Version

Sanctuary 3.1.0

Primitive

import { add, Just } from 'sanctuary'

add (1) (2) // ?
add (Just (1)) (Just (2)) // ?

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

lift2000

Maybe

Just

import { lift2, add, Just } from 'sanctuary'

let data1 = Just (1)
let data2 = Just (2)

lift2 (add) (data1) (data2) // ?

add 使用 lift2 提升後就能接受 Maybe。

lift2
Apply f => (a -> b -> c) -> f a -> f b -> f c
將 binary function 提升成能接受 Apply 的 function

a -> b -> c:一般 binary function

f a -> f b -> f c:回傳能接受 Apply 的 binary function

lift2001

Nothing

import { lift2, add, Just, Nothing } from 'sanctuary'

let data1 = Just (1)
let data2 = Nothing

lift2 (add) (data1) (data2) // ?

data 為 Nothing,則 lift2 (add) 也會回傳 Nothing。

lift2002

Either

import { lift2, add, Right } from 'sanctuary'

let data1 = Right (1)
let data2 = Right (2)

lift2 (add) (data1) (data2) // ?

add 使用 lift2 提升後也能接受 Either。

lift2003

Left

import { lift2, add, Right, Left } from 'sanctuary'

let data1 = Right (1)
let data2 = Left (2)

lift2 (add) (data1) (data2) // ?

data 為 Left,則 lift2 (add) 也會回傳 Left。

lift2004

Future

Resolved

import { resolve, fork } from 'fluture'
import { env as flutureEnv } from 'fluture-sanctuary-types'
import { create, env, add } from 'sanctuary'
import { error, log } from 'wink-fp'

let { pipe, lift2 } = create ({ checkTypes: true, env: env.concat (flutureEnv) })

let data1 = resolve (1)
let data2 = resolve (2)

pipe ([
  lift2 (add) (data2), 
  fork (error) (log)
]) (data1) 

第 6 行

let { pipe, lift2 } = create ({ checkTypes: true, env: env.concat (flutureEnv) })

Sanctuary 並不認識 Future 而導致無法通過 type checking,因此要使用 Fluture 提供的 fluture-sanctuary-types

11 行

pipe ([
  lift2 (add) (data2), 
  fork (error) (log)
]) (data1)

add 使用 lift2 提升後也能接受 Future。

lift2005

Rejected

import { resolve, reject, fork } from 'fluture'
import { env as flutureEnv } from 'fluture-sanctuary-types'
import { create, env, add } from 'sanctuary'
import { error, log } from 'wink-fp'

let { pipe, lift2 } = create ({ checkTypes: true, env: env.concat (flutureEnv) })

let data1 = resolve (1)
let data2 = reject (2)

pipe ([
  lift2 (add) (data2), 
  fork (error) (log)
]) (data1) 

data 為 Rejected,則 lift2 (add) 也會回傳 Rejected。

lift2006

Conclusion

  • 只要遵循 Fantasy Land 的 monadic type,function 就能彼此支援,因此 Sanctuary 的 lift2 也能使用 Fluture 的 Future
  • Sanctuary 的 type checking 預設並不認識 Future,但 Fluture 支援 Sanctuary,只要使用 fluture-sanctuary-types 後,Sanctuary 也能對 Future 使用 type checking
  • Ramda 的 lift 可同時提升 unary function 與 binary function,不像 Sanctuary 需要靠 map 提升 unary function,lift2 提升 binary function

Reference

Sanctuary, lift2