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

2022-07-08 15:42:20 字數 1582 閱讀 9365

「隱藏運算」 是我發明的詞,它的正式名稱是 「computation expressions」。

但 「computation expressions」 這個名稱實在讓人非常費解,也不能反映它的作用,不是乙個好名稱。

它的作用是在背後對兩個表示式進行一些操作,讓表示式們表面上看起來簡單。

請看例子:

let divideby bottom top =

match bottom with

| 0 -> none

| _ -> some <| top/bottom

let maybe = new maybebuilder()

let divideworkflow init x y z =

maybe

divideworkflow 12 3 2 1 // some(2)

divideworkflow 12 3 0 1 // none

請看那幾個let!, 表面上是 init 除以 x, 得出結果 a 再除以 y, 以此類推。這個表面上的邏輯非常清晰,但如果不是背後隱藏了一些處理(意思是,如果用let而不是用let!),這個**是跑不通的。因為 init 除以 x 得出來的 a 不是乙個數字(divideby 的返回值是 option, 不是 int), 因此如果讓 a 直接除以 y 會產生型別不匹配的錯誤。

簡單來說,let!表示 「computation expressions」, 也就是意味著在背後隱藏著一些我們表面上看不見的運算。

那麼,這個背後的運算具體是什麼?我們可以看到,全部let!都在maybe裡面,而 maybe 是由 maybebuilder 生成的,顯然,關鍵在於 maybebuilder 的定義:

type maybebuilder() =

member this.bind(x, f) =

match x with

| none -> none

| some a -> f a

member this.return(x) = some x

如上所示,這個 maybebuilder 的定義不是系統自帶的,要我們自己寫。可以看到,這個 「背後的**」 對 x:option 進行處理,如果是 none 則直接返回 none, 並且由於這個 none 會傳遞給下乙個let!, 因此可以預見一旦遇到 none, 後續的 f 就一律不會被運算,最終結果返回 none。如果是 some 則從 some 中提出取 a:int 並執行 f(a), 因此,經過這個背後的處理,表面上的a |> divideby y就不會出錯了。

由於標準庫里也帶了一些好用的函式,比如 option.bind, 因此 maybebuilder 也可以改寫成:

type maybebuilder() =

member this.bind(x, f) = option.bind f x

member this.return(x) = some x

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

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

函式式程式設計之 初窺F

大量講解函式式程式語言的書籍最終都會用fuctor,monad,monoids,範疇論等各種詞彙嚇退命令式語言玩家,所以我試圖避開這些問題,揭開這些複雜詞彙帶來的具有實戰意義的成果。另外我會盡量使用c 語言來描述函式式程式設計思想,因為c 某些語法和特性來自於函式式語言的啟發,但c 終究並不是正統的...

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

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