參考教材:Learn You a Haskell for Great Good (http://learnyouahaskell.com/)
操作環(huán)境:Ubuntu下Linux64位虛擬機
python入門編程, 之后用c++學習數(shù)據(jù)結(jié)構(gòu)宠纯,Haskell萌新卸夕。
由于對Haskell中一些詞語的中文翻譯并不了解,接下來的內(nèi)容中重點名詞將有英文和我理解的中文婆瓜。
Chapter5主要內(nèi)容(續(xù))
匿名函數(shù)(Lambdas)
lambdas基礎知識
lambdas是僅供單次使用的匿名函數(shù)快集。在寫法上它比普通的函數(shù)更簡單。在高階函數(shù)的實現(xiàn)中有時會遇到它廉白。適當使用lambdas函數(shù)可以增強代碼的可讀性碍讨。
匿名函數(shù),顧名思義蒙秒,就是函數(shù)沒有名稱。Haskell語言里的lambdas以\開頭宵统,后面跟參數(shù)晕讲,再接以->開頭的函數(shù)體。
比較匿名函數(shù)和普通的函數(shù)马澈,我們發(fā)現(xiàn)它們的結(jié)構(gòu)類似瓢省,只是匿名函數(shù)中不需要進行函數(shù)聲明和函數(shù)名稱,以->符號替代了普通函數(shù)中的=痊班。匿名函數(shù)同樣支持樣式匹配(pattern matching)勤婚,區(qū)別是我們針對一個參數(shù)只能使用一次樣式匹配。如果匹配失敗且得不到解決涤伐,程序會報錯終止馒胆。
lambdas示例
這里是幾個Lambdas函數(shù)的使用。右側(cè)兩個numLongChains函數(shù)放在一起作為對比凝果,在Load文件時祝迂,第三個函數(shù)尚不存在。
列表折疊函數(shù)(fold)
列表折疊函數(shù)可用于實現(xiàn)按元素遞歸列表的操作器净。它需要三個參數(shù)的輸入:二元函數(shù)型雳,起始值,待折疊列表。從起始值開始纠俭,按照折疊順序沿量,依次將當前值與待折疊列表中的元素進行二元操作,直到列表遍歷完畢冤荆。我們可以通過調(diào)用不同的函數(shù)來控制折疊的方式朴则。
左折疊(fold left)
右折疊(fold right)
與左折疊原理類似,區(qū)別是從待折疊列表的右側(cè)開始操作匙赞。這可能造成折疊函數(shù)的寫法上與左折疊有區(qū)別:用于累計的accumulator寫在右邊佛掖。
在這里使用右折疊,而不使用左折疊的理由是涌庭,左折疊用到的++函數(shù)需要遍歷元素芥被,而右折疊用到的:函數(shù)只需要O(1)的復雜度。在列表規(guī)模較大時坐榆,右折疊有優(yōu)勢拴魄。
右折疊的另一個優(yōu)勢是,借助于Haskell laziness的特性席镀,它可以針對一些無窮列表進行處理匹中。這部分的具體內(nèi)容建議參考Stack Overflow :foldl versus foldr behavior with infinite lists.下面是截圖。
折疊的一些例子
相似:掃描函數(shù)(scan)
scan函數(shù)可以用來監(jiān)控折疊的過程豪诲。同折疊一樣顶捷,它也有scanl和scanr兩種形式,要求二元函數(shù)操作屎篱,初始值服赎,待掃面列表。區(qū)別是交播,它還會保留所有中間變量重虑。具體例子如圖:
除了上面提到的函數(shù)外,還有不需要初始值(默認為首個)foldl1, foldr1, scanl1, scanr1函數(shù)秦士。這里暫時不詳細介紹缺厉。
右結(jié)合(right-associative)函數(shù)操作符$
通常情況下,使用空格分隔實現(xiàn)的函數(shù)是左結(jié)合的隧土,它們的優(yōu)先級極高提针。下面要講的函數(shù)操作符$卻是右結(jié)合的,它有最低的優(yōu)先級曹傀。代碼中的$表明关贵,這個符號右邊的內(nèi)容會先處理,處理完畢后作為參數(shù)傳遞給左邊的函數(shù)卖毁。
這一符號的第一個作用是揖曾,利用它的右結(jié)合特性落萎,減少代碼中括號的出現(xiàn),增強代碼的可讀性炭剪。
此外练链,這一符號還可以起到調(diào)用函數(shù)應用的作用(lets us treat function application like just another function)∨梗可能在想法上有點類似于函數(shù)指針媒鼓?
函數(shù)復合(function composition)
在Haskell里,我們使用.來實現(xiàn)函數(shù)復合错妖。需要注意绿鸣,f.g要求f的返回值和g的參數(shù)值有相同的類型。
由于函數(shù)復合符號.是右結(jié)合的暂氯,我們可以按照需要復合多個函數(shù)潮模。
如果我們希望處理的函數(shù)需要多個參數(shù)呢?我們可以運用前面的不完全函數(shù)來實現(xiàn)痴施。
綜合上面我們講到的擎厢,如果我們想要處理簡化一個多個括號的函數(shù),我們可以從最內(nèi)層開始寫辣吃,在需要的地方使用$符號減少括號动遭,使用不完全函數(shù)處理函數(shù)間的復合調(diào)用。
函數(shù)復合也可以在無點號(point-free)的情況下實現(xiàn)神得,具體參考前面函數(shù)部分的例子厘惦,在此不再贅述。