新聞中心
經(jīng)常有人覺(jué)得F#難懂難用,我覺(jué)得一部分原因是F#函數(shù)式語(yǔ)言中的函數(shù)接口(這里的接口指的是function signature, 我習(xí)慣叫它函數(shù)接口,如果對(duì)您閱讀帶來(lái)什么不便,請(qǐng)見(jiàn)諒). 看起來(lái)和我們平常熟悉的很不一樣(比如C#),導(dǎo)致一些朋友在嘗鮮階段遇到困難,進(jìn)而覺(jué)得其難懂難用,***徹底將F#打入冷宮。希望下面的內(nèi)容能讓大家覺(jué)得F#的函數(shù)不再難懂

10年積累的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶(hù)對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶(hù)得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先做網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有順河免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
還是老規(guī)矩,先來(lái)看一個(gè)例子
- let res = Seq.unfold (fun (a,b) ->Some(a,(a+b,a))) (0,1)
- Seq.iter(fun x -> printf "%d " x) ( Seq.take 10 res)
(這個(gè)例子中用到了F#中一個(gè)基本的immutable類(lèi)型Seq<'T>, 你可簡(jiǎn)單的把它等同于C# 3.0中鼎鼎大名的IEnumerable , 由于這不是本文的重點(diǎn),所以略去不表)
這段代碼是運(yùn)行結(jié)果是
0 1 1 2 3 5 8 13 21 34 (注意第二行的后面,我只取了sequence的前10個(gè)元素,Seq.take 10 res).看到輸出結(jié)果,我想大家都明白了這個(gè)程序***行是在生成Fibonacci數(shù)列,讓我們來(lái)看一下Seq.unfold方法的接口
val unfold: ('State -> ('T * 'State) option) -> 'State -> Seq<'T>
我想很多人在初學(xué)F#時(shí)看過(guò)這樣的函數(shù)接口說(shuō)明會(huì)感到很陌生吧,沒(méi)關(guān)系,這正是本文的目的,讓你對(duì)其不再陌生。
F#使用箭頭 "->"來(lái)標(biāo)記函數(shù)接口,比如 int -> string 就表示這是一個(gè)接受一個(gè)int型參數(shù)并返回一個(gè)string值的函數(shù)。比如 let f (x:int) = x.ToString()
了解了這個(gè)好象并不能幫助我們來(lái)理解Seq.unfold方法的接口,要理解它,我們還需要了解一些基本概念。
Higher-Order Function. 有可能以前你沒(méi)聽(tīng)說(shuō)過(guò)這種提法,但不要被這個(gè)陌生的名字嚇到,其實(shí)我們大家在中學(xué)時(shí)就接觸過(guò)這個(gè)東西了,不信你看這個(gè)sin(x+y) = sinxcosy+cosxsiny。三角和角公式,這個(gè)大家總該有些記憶吧? 有人要問(wèn)這和Higher-Order Function有什么關(guān)系呢?別急,讓我們先看看Higher-Order Function的定義。SICP 里是這樣定義的:Procedures that manipulate procedures are called higher-order procedures。(定義里的procedures就是我們這里說(shuō)的Function的意思).定義中提到的操作(manipulate)函數(shù)不由讓我們想入非非,怎么樣操作函數(shù)?把函數(shù)當(dāng)作普通的參數(shù)來(lái)理解不就簡(jiǎn)單多了,( 簡(jiǎn)單點(diǎn)就是一個(gè)函數(shù)接受的參數(shù)可以是函數(shù),它的返回值也可以是函數(shù))。那為什么要叫Higher-Order procedures呢?你的老板可以成天讓你做這個(gè)干那個(gè),你能反過(guò)來(lái)指揮你老板做事么J 再看下我上面說(shuō)的三角和角公式,把sin和cos都看成是函數(shù)的話(huà),呵呵,是不是我們?cè)诟咧芯徒佑|過(guò)Higher-Order Function了?
有了Higher-Order Function的概念,好象還是不能讓我們很快看明白Seq.unfold該怎么用。讓我們接著來(lái)看一個(gè)簡(jiǎn)單的函數(shù)
let add x y = x+y ( 我們看到這個(gè)函數(shù)的接口是val add: int -> int -> int)
讓我們接著分析一下這個(gè)簡(jiǎn)單的方法,F(xiàn)#中箭頭"->“來(lái)表示一個(gè)函數(shù),并且它是從右到左結(jié)合的,所以我們可以把int->int->int看成int->(int->int),結(jié)合剛剛說(shuō)過(guò)的Higher-Order Function,這個(gè)就變得很易容易理解了,Add接受一個(gè)int型參數(shù),返回一個(gè) int->int的函數(shù)。讓我們根據(jù)這個(gè)把a(bǔ)dd來(lái)改寫(xiě)一下使其更直觀(guān)一些
let add x y = (fun x -> (fun y -> x+y) ) (這個(gè)很容易讀懂了吧? 接受一個(gè)參數(shù)x,返回一個(gè)函數(shù) fun y -> x+y,返回的函數(shù)接受一個(gè)參數(shù)y,并且返回x+y的值。)
有了上面的基礎(chǔ),讓我們更進(jìn)一步,
let add10 = add 10
我想這個(gè)大家應(yīng)該都能看明白了吧, let add10 = (fun x -> (fun y -> x+y)) 10 = fun y -> 10+y。類(lèi)似于add10這種用法,在F#中叫做Currying Fuction, 這里的curry跟咖哩沒(méi)任何關(guān)系,它和Haskell語(yǔ)言的命名一樣,都是為了紀(jì)念著名邏輯學(xué)專(zhuān)家Haskell Curry,當(dāng)然currying function也不是F#獨(dú)用的,實(shí)際上你幾乎可以在任何函數(shù)式語(yǔ)言上看到它的身影。
講了這么多了,讓我們回到最開(kāi)始的例子,
val unfold: ('State -> ('T * 'State) option) -> 'State -> Seq<'T>
現(xiàn)在這個(gè)看起來(lái)沒(méi)前面那么難了吧, unfold方法接受一個(gè)('State -> ('T * 'State) option)的參數(shù),返回一個(gè)接受'State并返回Seq<'T>的函數(shù)。接受的('State->('T *'State) option)的參數(shù)又是什么? 當(dāng)然是一個(gè)接受'State參數(shù)并返回 ('T * 'State) option的函數(shù)。接著我們采用笨辦法來(lái)理解let res = Seq.unfold (fun (a,b) ->Some(a,(a+b,a))) (0,1)一一對(duì)應(yīng)之,(a,b)對(duì)應(yīng)于'State, Tuple(a,(a+b,a))中逗號(hào)前的a對(duì)應(yīng)于'T,后面的(a+b,a)對(duì)應(yīng)于 'T*'State,因?yàn)槲覀兛吹浇涌谡f(shuō)明中是('T * 'State) option,所以我們相應(yīng)的加上Some關(guān)鍵字(有關(guān)option type,參見(jiàn)上一篇),后半部分我就不多解釋了,通過(guò)一一對(duì)應(yīng),我們看到Seq里存的值是Tuple(a,(a+b,a))中的***項(xiàng),也就是逗號(hào)前的a了。這下你明白怎么讀懂一個(gè)函數(shù)接口了吧?
如果你剛剛開(kāi)始學(xué)F#,請(qǐng)做幾個(gè)練習(xí)鞏固一下今天學(xué)的知識(shí)吧?你能根據(jù)下面所寫(xiě)的函數(shù)接口構(gòu)造一個(gè)函數(shù)么?
- 'a -> ('a->'b)->'b
- ('a->'b) ->('c -> 'a) -> 'c -> 'b
- (’T -> bool) -> ‘T list -> ‘T list
F#函數(shù)式語(yǔ)言總結(jié):
1.F#函數(shù)式語(yǔ)言中每個(gè)函數(shù)都有一個(gè)返回值,這個(gè)返回值可以是具體的值,也可以是另一個(gè)函數(shù)(unit表示函數(shù)返回值為空(void)). 當(dāng)在讀一個(gè)函數(shù)接口說(shuō)明時(shí),最右面箭頭"->"后面的部分,表示的就是該函數(shù)的返回值。F#中的每個(gè)函數(shù)都只能接受一個(gè)參數(shù),同樣,這個(gè)參數(shù)可以是具體的值,也可以是一個(gè)參數(shù)。
2. Higher-Order function 和Currying function是理解并能熟練運(yùn)用函數(shù)式編程的重要基石,希望還不太明白的朋友能好好理解我上面的例子,把基礎(chǔ)打好。
本文來(lái)自芭蕉的博客園文章《結(jié)合實(shí)例實(shí)習(xí)F#(三)--理解函數(shù)式語(yǔ)言中的函數(shù)》
名稱(chēng)欄目:結(jié)合實(shí)例理解F#函數(shù)式語(yǔ)言中的函數(shù)
本文路徑:http://m.5511xx.com/article/copsido.html


咨詢(xún)
建站咨詢(xún)
