函式式程式設計之 初窺F

2022-02-21 05:27:12 字數 2025 閱讀 1198

大量講解函式式程式語言的書籍最終都會用fuctor,monad,monoids,範疇論等各種詞彙嚇退命令式語言玩家,所以我試圖避開這些問題,揭開這些複雜詞彙帶來的具有實戰意義的成果。另外我會盡量使用c#語言來描述函式式程式設計思想,因為c#某些語法和特性來自於函式式語言的啟發,但c#終究並不是正統的函式式語言,隨著對話題的深入,我們不可避免要使用f#來描述某些特性。所以本文會對f#的基礎語法做一些簡單了解,本文並不是乙個純粹的f#教程,只會提及必要的f#語法,最終循序漸進穿插在整個文章中。

在函式式語言裡,函式被設計為一等公民,也就是說函式跟int, bool等型別並沒有什麼區別,例如在命令式語言的函式定義中,引數可以是int值,那麼在函式式語言裡,引數也可以是乙個函式。這種特性在c#其實也是工作的:

public void convert(funcselector)
這種設計在函式式語言裡會有更進一步的體現:

在f#中宣告乙個簡單型別用let:

let x = 6
宣告乙個函式:

let f x = x + 1
或者:

let f = fun x -> x + 1
無論是申明型別還是函式,都用let,這並不是乙個巧合,因為在語言設計者眼裡,函式和其他型別都是一樣的。

另外需要注意,不要看到上面的**認為f#是一門動態語言,f#毫無疑問是一門靜態語言,通過type inference來工作。它要比c#中的var強大的多,只有在少數情況下需要加型別宣告,考慮下面的例子:

let stringlength x = x.length
上面的**並不能正常工作,僅僅通過x.length無法推斷出x的型別,此時需要顯示標註型別:

let stringlength (x:string) = x.length
當然你還可以向其它語言那樣,標註函式的返回值型別,雖然此時此刻這一步並不是必須的:

let stringlength (x:string) :int = x.length
let printnumber x = printf "%i" x
這段**不論你輸入什麼樣的x,它只是列印了乙個數字(***),他的返回值是什麼?不像c#中的void,f#會返回乙個真實的型別unit,注意unit並不是null或者void,他是乙個型別,如int一樣。

f#裡有一些常用的資料結構,例如tuplerecord typesdiscriminated unionoptionlist,不要擔心,目前你只需要知道tuple就可以了。

除了諸如int,string等型別,如何快速的組合幾個型別在一起呢?宣告乙個類?答案是:no, 比如("hello", 1)就是有乙個stringint組合在一起的tuple型別,他的型別為string * int。例如下面的函式:

let sum (x, y) = x + y
它的方法簽名是:sum : x:int * y:int -> int即函式名為sum,接受int * int型別的乙個tuple,返回int型別。

如果要接受兩個int型別的引數應該這樣定義的:

let sum x y = x + y

F 程式設計 函式式程式設計之Records

當你想把資料組成乙個結構化的格式,而不需要太複雜的語法時,你可以使用f 中的record型別。record型別與c語言的struct型別基本一樣,儲存一組型別的值,通過欄位的值來獲取。定義乙個record型別很簡單,只需要在大括號內定義系列的名稱 型別就可以。要例項化乙個record,只需要提供對應...

F 函式式程式設計之 隱藏運算

隱藏運算 是我發明的詞,它的正式名稱是 computation expressions 但 computation expressions 這個名稱實在讓人非常費解,也不能反映它的作用,不是乙個好名稱。它的作用是在背後對兩個表示式進行一些操作,讓表示式們表面上看起來簡單。請看例子 let divid...

F 函式式程式設計之 面向鐵道程式設計

原文 參考 不長,先看 吧,我在 後面寫講解。type request let validatename request match request with when name error name must not be blank ok request let validateemail fu...