摘要:接受另一個(gè)函數(shù)作為參數(shù),然后用接受的這個(gè)新函數(shù)處理,將結(jié)果再次傳給,最后將實(shí)例化的新對(duì)象返回。空值檢查就是個(gè)不錯(cuò)的例子這個(gè)實(shí)現(xiàn)里,只在為合法值非空時(shí),傳入。但不論怎么變化,她們也都和一樣遵守上面提到的規(guī)則。
大多數(shù)關(guān)于monad的教程都和老太太的裹腳布一樣,又臭、又長(zhǎng),說不清、道不明。當(dāng)然我也不偉大,沒法保證我寫的一定更明了,更生動(dòng),甚至更屌?不過我至少可以確定,我這篇更簡(jiǎn)潔。浪費(fèi)不了你多少時(shí)間的!
廢話不多說,先看下面這個(gè)對(duì)象Foo。她就是個(gè)monad。你必定會(huì)吃驚道:我擦,這是什么意思?不要急,故事要從頭說,我們還是先來分析下Foo到底是怎么干活的:
function Foo(value) { this.get = ()=> value; this.map = fn => { let result = fn(value); return new Foo(result); }; }
Foo接受了一個(gè)value,而且一直都沒改變她的值。Foo里提供了一個(gè)get方法使得外部調(diào)用者可以獲取value,還有一個(gè)牛逼的方法叫map。map接受另一個(gè)函數(shù)(handler)作為參數(shù),然后用接受的這個(gè)新函數(shù)handler處理value,將結(jié)果再次傳給Foo,最后將實(shí)例化的新Foo對(duì)象返回。
因?yàn)?b>map返回一個(gè)Foo的實(shí)例,于是map的方法是可以被鏈?zhǔn)秸{(diào)用的:
let one = new Foo(1); let two = one.map(x => x + 7).map(x => x / 2).map(x => x - 2); two.get() === 2;
鏈?zhǔn)秸{(diào)用high不 high?她允許我們可以按照期望,對(duì)x執(zhí)行順序操作,這種更“自然”的風(fēng)格絕對(duì)比下面這種瘋狂嵌套的風(fēng)格要好:
//嵌套組合的方式長(zhǎng)這個(gè)樣子, //我們必須從右向左讀,才能得出結(jié)論 //而且你說實(shí)話,這風(fēng)格,你喜歡么? let two = minusTwo(divideByTwo(addSeven(1)));
而且每一個(gè)步驟里處理value到下一個(gè)Foo實(shí)例的邏輯我們都可以抽離出去。
再來看看另一個(gè)monad,我們姑且稱之為Bar吧:
function Bar(value) { this.get = ()=> value; this.map = fn => { let result = fn(value); console.log(result); return new Bar(result); }; }
如果這時(shí)候我有一系列操作想順序作用在value上,而且還要在每次變化時(shí)打印出來新的value,就可以利用Bar把下面這種原始的,二逼的代碼:
let stepOne = something(1); console.log(stepOne); let stepTwo = somethingElse(stepOne); console.log(stepTwo); let stepThree = somethingDifferent(stepTwo); console.log(stepThree);
重構(gòu)成下面這種優(yōu)雅的,高端的樣子了:
new Bar(1) .map(something) // console >> logs new value .map(somethingElse) // console >> logs new value .map(somethingDifferent); // console >> logs new value
現(xiàn)在你應(yīng)該懂什么是monads了。我完成諾言了哦!Monads可以粗略的歸納出下面這些規(guī)則:
monad總會(huì)包含一個(gè)值
monad有一個(gè)map方法,而且該方法會(huì)接受一個(gè)函數(shù)(handler)作為參數(shù)
map通過上一步提到的handler處理value(還可能有些其他邏輯),并獲取其結(jié)果
map最后返回一個(gè)new [Monad],以完成鏈?zhǔn)秸{(diào)用
目前能想到的就這些了。如果上述的例子你都理解了,那你就懂什么是Monads了。如果你還再等什么黑魔法或者驚奇算法,那抱歉了,還真沒有!
理論上,我們?nèi)我庑薷?b>map的實(shí)現(xiàn),任何可以在各步驟handler之間的邏輯都行 - 例如:決定傳什么內(nèi)容到下一步,或者對(duì)上一步handler處理的結(jié)果做點(diǎn)兒什么。
空值檢查就是個(gè)不錯(cuò)的例子:
function Maybe(value) { this.get = ()=> value; this.map = fn => { if (value === null) { return new Maybe(null); } else { return new Maybe(fn(value)); } }; }
這個(gè)實(shí)現(xiàn)里,map只在value為合法值(非空)時(shí),傳入handler。否則就只返回一個(gè)自身的copy。利用上面的非空檢查的Monad函數(shù)Maybe,我們可以把下面這個(gè)冗長(zhǎng)矬的代碼:
let connection = getConnection(); let user = connection ? connection.getUser() : null; let address = user ? user.getAddress() : null; let zipCode = address ? address.getZip() : null;
重構(gòu)成這個(gè)樣子:
let zipCode = new Maybe(getConnection()) .map(c => c.getUser()) .map(u => u.getAddress()) .map(a => a.getZip()); //最后得到的要么是真正的zipCode(每一步都正確處理) //要么就是個(gè)null zipCode.get();
希望今天的說教已經(jīng)說明了monads和她的map方法為什么這么牛逼了!關(guān)于這點(diǎn),我倒是不懷疑你也能自己想出來^^
還有其他很多種monads,都有不同的用法和用途。但不論怎么變化,她們也都和Foo、Bar一樣遵守上面提到的規(guī)則。
掌握了這些技巧,你基本就可以裝做一個(gè)會(huì)寫函數(shù)式的“牛人”了!
原文地址:Monads Explained Quickly
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79149.html
摘要:函數(shù)式編程,一看這個(gè)詞,簡(jiǎn)直就是學(xué)院派的典范。所以這期周刊,我們就重點(diǎn)引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對(duì)編程語(yǔ)言的理解更加融會(huì)貫通一些。但從根本上來說,函數(shù)式編程就是關(guān)于如使用通用的可復(fù)用函數(shù)進(jìn)行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...
摘要:我之前寫過關(guān)于的文章,,最近在工作中用到比較多了,頓時(shí)覺得確實(shí)是比較優(yōu)秀的一個(gè)。 我之前寫過關(guān)于cypress的文章,https://segmentfault.com/a/11...,最近在工作中用到cypress比較多了,頓時(shí)覺得cypress確實(shí)是比較優(yōu)秀的一個(gè)。 1. 軟件安裝. 2. 安裝cypress 安裝cypress客戶端:http://download.cypress...
摘要:來自不同視圖的行為需要變更同一狀態(tài)。圖解后端的行為,響應(yīng)在上的用戶輸入導(dǎo)致的狀態(tài)變化。中的非常類似于事件每個(gè)都有一個(gè)字符串的事件類型和一個(gè)回調(diào)函數(shù)。 什么是Vuex? Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。 Vuex采用和Redux類似的單向數(shù)據(jù)流的方式來管理數(shù)據(jù)。用戶...
摘要:后文將圍繞做一些介紹。盡管如此,的使用對(duì)新手而言仍然充滿了困難。本系列文章基本為個(gè)人見解,難免有錯(cuò)誤與誤解,如有客觀錯(cuò)誤歡迎提出。 前言 說到Android的污點(diǎn)分析框架,網(wǎng)上的搜索結(jié)果大多指向靜態(tài)的FlowDroid與動(dòng)態(tài)的TaintDroid。盡管由于加固、混淆等技術(shù)使得針對(duì)Android的靜態(tài)分析越來越困難,但靜態(tài)分析的無(wú)先驗(yàn)分析能力無(wú)法被動(dòng)態(tài)分析取代,使得靜態(tài)分析仍有發(fā)揮空間。...
閱讀 3109·2021-10-13 09:40
閱讀 3964·2021-09-22 15:51
閱讀 1509·2021-09-22 15:48
閱讀 1077·2021-09-06 15:00
閱讀 1802·2019-08-30 15:43
閱讀 2370·2019-08-29 18:35
閱讀 1683·2019-08-29 16:18
閱讀 3625·2019-08-29 12:49