-
Notifications
You must be signed in to change notification settings - Fork 0
函子 #18
Copy link
Copy link
Open
Description
函子(Functor)
haskell 内的 Functor 定义:
class Functor f where
fmap :: (a -> b) -> f a -> f b 简单来说,Functor 就是一个定义了 fmap 方法的对象,它可以被作为 map 函数的参数。
map 接收一个 a -> b 类型的函数和一个函子 f a,返回一个新的函子 f b 类型的函数。
function plusOne(x) {
return x + 1
}
plusOne([3]) // ! wrongR.map(plusOne, [3]) // [4]
// ---> [3] -> [plsuOne(3)]
R.map(plusOne, MyObject(1)) // MyObject(plusOne(1))
//=> MyObject(2)
R.map(function(x) { return 'I am ' + x}, MyObject("Yo")) // MyObject("I am Yo")
R.map(function(x) { return x.id}, MyObject({id: 2718})) // MyObject(2718)
// map 方法就像是打开 MyObject,对 MyObject 内的值进行操作,再关闭 MyObject
class MyObject {
constructor(value) {
this.__value = value
}
map(func) {
return new MyObject(func(this.__value))
}
}
// 我们通过对 MyObject 定义 map, MyObject 可以看做一个 Functor
// some use of Functor
// type safe
class Maybe {
constructor(value) {
this.__value = value
}
map(func) {
return this.__value ? new Maybe(func(this.__value)) : new Maybe(null)
}
}
R.map(plusOne, new Maybe(1)) // Maybe(2)
R.map(plusOne, new Maybe(null) // Maybe(null)
// 对于 Functor,我们需要调用 map 方法来修改它的值,而不能直接修改它的值。
//! 动态的类型安全
// default value
class Either {
// left as default
constructor(left, right) {
this.__left = left
this.__right = right
}
map(func) {
return this.right
? new Either(this.__left, func(this.__right))
: new Either(func(this.__left), this.__right)
}
}
R.map(plusOne, new Either(1, 2)) // Either(1, 3)
R.map(plusOne, new Either(1, null)) // Either(2, null)
// auto handle Promise
Promise.prototype.map = function(func) {
let thisPromise = this
return this.then(function(response) {
return func(response)
})
}
function handleResponse(response) {
return response.json().then(json => {
// doSthWithJson
return 'done'
})
}
let mapped = R.map(handleResponse, fetch('/someAPI'))
await mapped // 'done'
// DEMO
// we have a side effect
let setProp = function (prop, value, obj) {
obj[prop] = value
return obj
}.autoCurry()
let title = document.getElementById('title')
// getGreeting :: User -> String
let getGreeting = compose(R.concat("Welcome "), R.prop("name"))
// updateGreetingHtml :: User -> undefined
let updateGreetingHtml = compose(setProp('textContent', R.__, title), getGreeting)
updateGreetingHtml(currentUser)
// what if we dont have a currentuser
map(updateGreetingHtml, Either({name: 'Guest'}, currentUser))
// 使用 Functor,你不能直接操作 Functor 的值,在程序其他地方必须使用 map(包括 filter) 来进行操作,
// 你不必关心其内部结构,只用知道他可以被 mapReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels