點燈坊

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

使用 map 提升 Unary Function

Sam Xiao's Avatar 2021-07-16

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

Version

Sanctuary 3.1.0

Primitive

import { negate, Just } from 'sanctuary'

let data = 1

negate (data) // ?
negate (Just (data)) // ?

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

map000

Maybe

Just

import { map, negate, Just } from 'sanctuary'

let data = Just (1)

map (negate) (data) // ?

使用 mapnegate 提升成 negate_,因此能接受 Just。

map
Functor f => (a -> b) -> f a -> f b
將 unary function 提升成能接受 Functor 的 function

a -> b:一般 unary function

f a -> f b:回傳能接受 Functor 的 unary function

map001

Nothing

import { map, negate, Nothing } from 'sanctuary'

let data = Nothing

map (negate) (data) // ?

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

map002

Either

import { map, negate, Right } from 'sanctuary'

let data = Right (1)

map (negate) (data) // ?

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

map003

Left

import { map, negate, Left } from 'sanctuary'

let data = Left (1)

map (negate) (data) // ?

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

map004

Future

Resolved

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

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

let data = resolve (1)

pipe ([
  map (negate), 
  fork (error) (log)
]) (data)

第 6 行

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

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

10 行

pipe ([
  map (negate), 
  fork (error) (log)
]) (data)

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

map005

Rejected

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

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

let data = reject (1)

pipe ([
  map (negate), 
  fork (error) (log)
]) (data) 

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

map006

Conclusion

  • Ramda 使用 lift 提升 unary function 支援 Apply,但 Sanctuary 使用 map 提升 unary function 支援 Functor,因為 Maybe、Either 與 Future 既是 Functor 也是 Apply,因此 map 亦適用
  • 只要遵循 Fantasy Land 的 monadic type,function 就能彼此支援,因此 Sanctuary 的 map 也能使用 Fluture 的 Future
  • Sanctuary 的 type checking 預設並不認識 Future,但 Fluture 支援 Sanctuary,只要使用 fluture-sanctuary-types 後,Sanctuary 也能對 Future 使用 type checking

Reference

Sanctuary, map