所以函數式編程是什麼(ㄧ)

閱讀時間約 4 分鐘

前面談了那麽多函數式編程與物件導向的差異,但我們還沒定義函數式編程。就像物件導向,函數式編程沒有明確的定義,每個人對於什麼是函數式編程都有不同的看法。在這裡我會總結前面的討論,給出我對於函數式編程的觀點。


物件導向注重封裝與延展性,因此一般基於三個機制:繼承、多型、封裝,它們代表了物件導向所重視的部分。而函數式編程著重於規則,認為規則的定義應該要明確且嚴格,因此它特別重視實現規則的機制。我認為的函數式編程則基於三個機制:類型、泛型、多型。


「類型」的機制指的是每個變數應該要有唯一的類型,它用來描述值的資料結構。它同時可以用來描述資料的意義,因此不是結構一樣就是相同的類型,也就是所謂的nominal type。函數式編程強調變數類型的明確性,因此不使用像是類別的抽象類型描述資料,而是透過多型描述抽象概念。相對地,為了讓類型具有延展性與可重用性,函數式編程使用複合類型組合多個類型,而非透過繼承延伸已有的類型。對於函數式編程,函式本身也有類型,而它只是其中一種複合類型而已,因此使用函式作為值使用是很正常的。函式的類型描述的是函式的行為,更廣義來說,函式的非同步標示符(async)、可拋出例外標示符(throws)等都可以算作函式類型的一部分。在Haskell則是使用Monad描述這些結構。總結來說,類型的職責是描述資料結構乃至程式結構,而非透明的特性能讓我們根據架構設計賦予這些結構唯一的語義。


「泛型」的機制透過參數化類型實現變數類型的抽象化。不同於物件導向的子類關係,它能保證類型之間的同調性,而這種同調性本身可以用來描述整體的結構。參數化的類型讓我們無法知道變數的具體類型,這使得我們必須以獨立於類型的方式處理它,除非程式語言本身允許實體類型檢查。這種必須與具體類型無關的限制形成對類型的抽象化,泛型本身並不能直接描述有意義的抽象類型,通常會搭配約束和多型的機制使用。如果程式語言不允許子類關係,那麽泛型就是唯一能使用非特定類型的方法,否則所有變數都只能有特定且具體的類型。對類型進行參數化代表把類型本身當作一種數值,並使用一個佔位符取代。更廣義的,不只有類型可以參數化,複合類型的建構子也能參數化,而它具有和類型不同的種類(kind),這種將類型作為值看待的方法使我們能更進一步地思考程式的抽象結構。總結前面的討論,泛型能將具體的結構從程式中抽離出來,變成可替換的抽象結構,這種特定的抽象就是這個機制的職責。


函數式編程的「多型」與物件導向的不同,它指的是特設多型,透過讓一個函式針對不同特定的類型做出不同的行為,讓我們可以描述抽象概念。特設多型能讓程式在不同地方對不同類型實作同一個概念,這為抽象概念提供擴展的能力。這種可擴展的語義讓我們無法直接透過具體類型決定函式的行為,因而形成抽象的概念。函數式編程的特設多型可以藉由對類型參數的約束實現,其中約束通常是使用介面/特性系統描述。對於不允許繼承和實體類型檢查的程式語言,這是唯一能讓同一個函式對不同類型具有不同行為的方法,而這與流程控制的分支不同,它的實際行為可以藉由實體化的類型決定,而不是在執行時期才決定。因此,多型的職責是為相同概念實現不同的行為,並讓我們在程式中實現與描述抽象概念。


函數式編程的這些機制與物件導向很像,但函數式編程的機制是根據能力和規則設計的,而非像是物件導向根據某種特定的面向設計,因此對於問題的解決方案比較不容易出現多種可能的實現方法。例如類型只能描述具體資料結構,不能描述抽象概念;泛型可以用來抽象化資料結構,但不會抹去類型資訊;多型必須藉由泛型與約束完成,它是唯一能實現擴展抽象概念的機制。而物件導向的一些機制對於函數式編程是多餘的,甚至是有害的。例如子類關係讓我們難以判斷變數是否是抽象的;變數的實體類型檢查讓泛型失去行為的一致性。相對的,函數式編程的機制之間的能力是沒有重合的,因此能將各自的能力發揮到極致。這種設計讓變數、函式、介面等編程實體僅具有最少的能力,使得我們能更準確掌握各個部分的程式碼能做什麼和該做什麼。這種最小化能力、最大化用處的設計就是我認為的函數式編程最重要的原則,而這三個機制從語言級別上遵從與支援這個原則。

4會員
28內容數
這不是教你如何從物件導向到函數式編程的入門教程。我會深入探討物件導向與函數式編程的差異,並討論為什麼你應該使用函數式編程並徹底放棄物件導向。
留言0
查看全部
發表第一個留言支持創作者!
have bear的沙龍 的其他內容
說到物件導向就必須提五個原則,統稱SOLID,它被認為是物件導向的重要概念。這五個原則並不只適用於物件導向,事實上它很像函數式編程的習慣。它的命名很奇怪且容易讓人混淆,所以我會用我自己的翻譯解釋。 Single Responsibility Principle 是「單一職責原則」,認為一個模組
讓我在這篇文章總結一下前面對物件導向設計的討論,我們討論了物件導向的四個特性:繼承、抽象、多型、封裝,分析了它們的問題,並跟函數式編程的思維做比較。我們引入了與之相對應的特性:泛型、特性系統、模組化,有些特性雖然跟那四個特性很像,但在一些細微的地方有不同的詮釋,使得整體思考方式很不一樣。 「繼
物件導向設計的一個重點就是封裝,這有很多層面上的意義,但基本上就是控制物件的成員變數和方法的存取權。物件導向的封裝還跟繼承機制有關,這使得有一些時候我們逼不得已必須把函式定義在類別上,這種做法使得物件的功能變得難以拆解。封裝應該是模組的職責,並不需要再給物件相同的能力。 一般的模組系統就是把相
上一篇文章提到有些介面不應被繼承,但物件導向的子類別只能繼承父類別的介面,因而產生一些不合適的介面實作。trait/typeclass則沒有這種繼承機制,這似乎使需要繼承的特性無法直接使用。然而函數式導向比起繼承,更適合使用組合,根本不需要使用繼承疊加特性。 資料類型的定義往往跟怎麼建構模型相
類似於trait/typeclass的特性系統能提供程式「延展性」,它能讓函式針對不同的類型做出不同的行為。這種機制與物件導向的繼承非常像,然而特性系統的彈性比較大一點,而且概念上也有一些差別。為了探討討論這些差異,我們必須深入了解繼承機制到底是什麼。 繼承並不是建立子類關係的唯一方法。所謂的
所謂的多型是讓一個函式或是資料結構能擁有多個不同的類型,其中上一篇文章所談的就是參數多型(parametric polymorphism),這篇文章將繼續討論特設多型(ad hoc polymorphism)。特設多型跟泛型的差別在於:泛型函式對於所有的類型只能有一種實作,而特設多型會根據類型有不同
說到物件導向就必須提五個原則,統稱SOLID,它被認為是物件導向的重要概念。這五個原則並不只適用於物件導向,事實上它很像函數式編程的習慣。它的命名很奇怪且容易讓人混淆,所以我會用我自己的翻譯解釋。 Single Responsibility Principle 是「單一職責原則」,認為一個模組
讓我在這篇文章總結一下前面對物件導向設計的討論,我們討論了物件導向的四個特性:繼承、抽象、多型、封裝,分析了它們的問題,並跟函數式編程的思維做比較。我們引入了與之相對應的特性:泛型、特性系統、模組化,有些特性雖然跟那四個特性很像,但在一些細微的地方有不同的詮釋,使得整體思考方式很不一樣。 「繼
物件導向設計的一個重點就是封裝,這有很多層面上的意義,但基本上就是控制物件的成員變數和方法的存取權。物件導向的封裝還跟繼承機制有關,這使得有一些時候我們逼不得已必須把函式定義在類別上,這種做法使得物件的功能變得難以拆解。封裝應該是模組的職責,並不需要再給物件相同的能力。 一般的模組系統就是把相
上一篇文章提到有些介面不應被繼承,但物件導向的子類別只能繼承父類別的介面,因而產生一些不合適的介面實作。trait/typeclass則沒有這種繼承機制,這似乎使需要繼承的特性無法直接使用。然而函數式導向比起繼承,更適合使用組合,根本不需要使用繼承疊加特性。 資料類型的定義往往跟怎麼建構模型相
類似於trait/typeclass的特性系統能提供程式「延展性」,它能讓函式針對不同的類型做出不同的行為。這種機制與物件導向的繼承非常像,然而特性系統的彈性比較大一點,而且概念上也有一些差別。為了探討討論這些差異,我們必須深入了解繼承機制到底是什麼。 繼承並不是建立子類關係的唯一方法。所謂的
所謂的多型是讓一個函式或是資料結構能擁有多個不同的類型,其中上一篇文章所談的就是參數多型(parametric polymorphism),這篇文章將繼續討論特設多型(ad hoc polymorphism)。特設多型跟泛型的差別在於:泛型函式對於所有的類型只能有一種實作,而特設多型會根據類型有不同
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
「大下後,六七日不大便」,攻下後,結果又六七天沒有大便,「煩不解,腹滿者」,仍然煩躁,代表津液還沒回頭,腸子裡面仍有燥屎堵到,這是藥劑不足,下手太輕,「所以然者,又有宿食故也,宜大承氣湯」,再開大承氣湯給他,沒有關係。怎麼知道腸子裡面沒有燥屎了呢?看小便的顏色,小便的顏色從深黃變成淡黃色時就可以停藥
二五二:「陽明證」,其人善忘者,必有蓄血,所以然者,本有久瘀之血,故令善忘;矢雖鞕,大便反易,其色必黑,宜「抵當湯」下之。 「陽明證,其人善忘者,必有蓄血」,陽明病患者,常常東西記不清楚,剛剛講的可能馬上忘了,最近的事都忘了,可是很久以前的事會記得,蓄血就是身體裡面有瘀血,「所以然者,本有久瘀之血
「陽明病,不能食」,病患者不能吃東西了,這是中寒,代表腸胃不蠕動了,腸胃虛寒,「攻其熱必噦」,如果把不能食誤認為是有東西堵在腸胃中,而用寒涼的藥去攻下,像白虎湯裡的石膏、知母,其它如大黃、黃芩、黃連、茵陳、梔子、連翹、銀花、薄荷、犀角等都是寒涼的藥,胃會更寒,就不停的打嗝,此為「噦」,為胃氣將絕的現
Thumbnail
#寵物溝通 案例分享 寵物:貓咪 名字:大寶
「下之後,復發汗」,攻下了以後,腸胃津液傷到了,陰虛掉了,又發汗造成陽也虛掉了,陰陽兩虛,「必振寒」,病人就會覺得身體裡面很冷,手腳冰冷的現象,「脈微細」,脈摸起來跳的很慢又很微弱,「所以然者,以內外俱虛故也」,造成這樣的原因是內外都虛掉了,這時候就會用到「四逆湯」來救逆。
倪氏曰:裡虛不能發汗的情況又有表證時應該怎麼辦?就用「小建中湯加黃耆」,黃耆可以固表補氣,讓三焦通道暢通,屬於氣藥,走表,目的就是減少發汗,先把裡扶正而發一點表。
Thumbnail
作為溝通社團的一員,其實我原本以為自己在裡頭的定位會是像年輕時一樣是個激進份子,但1124的結果令我的心態轉變了不少。不論是看待社運、看待政治的操作與許多人口中的「政治酬庸」,我以前宛如「左膠」般的鋒利被磨平,逐漸把自己的思想核心拉回到左與右的中心,也就是為自己的政治意念取得平衡。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
「大下後,六七日不大便」,攻下後,結果又六七天沒有大便,「煩不解,腹滿者」,仍然煩躁,代表津液還沒回頭,腸子裡面仍有燥屎堵到,這是藥劑不足,下手太輕,「所以然者,又有宿食故也,宜大承氣湯」,再開大承氣湯給他,沒有關係。怎麼知道腸子裡面沒有燥屎了呢?看小便的顏色,小便的顏色從深黃變成淡黃色時就可以停藥
二五二:「陽明證」,其人善忘者,必有蓄血,所以然者,本有久瘀之血,故令善忘;矢雖鞕,大便反易,其色必黑,宜「抵當湯」下之。 「陽明證,其人善忘者,必有蓄血」,陽明病患者,常常東西記不清楚,剛剛講的可能馬上忘了,最近的事都忘了,可是很久以前的事會記得,蓄血就是身體裡面有瘀血,「所以然者,本有久瘀之血
「陽明病,不能食」,病患者不能吃東西了,這是中寒,代表腸胃不蠕動了,腸胃虛寒,「攻其熱必噦」,如果把不能食誤認為是有東西堵在腸胃中,而用寒涼的藥去攻下,像白虎湯裡的石膏、知母,其它如大黃、黃芩、黃連、茵陳、梔子、連翹、銀花、薄荷、犀角等都是寒涼的藥,胃會更寒,就不停的打嗝,此為「噦」,為胃氣將絕的現
Thumbnail
#寵物溝通 案例分享 寵物:貓咪 名字:大寶
「下之後,復發汗」,攻下了以後,腸胃津液傷到了,陰虛掉了,又發汗造成陽也虛掉了,陰陽兩虛,「必振寒」,病人就會覺得身體裡面很冷,手腳冰冷的現象,「脈微細」,脈摸起來跳的很慢又很微弱,「所以然者,以內外俱虛故也」,造成這樣的原因是內外都虛掉了,這時候就會用到「四逆湯」來救逆。
倪氏曰:裡虛不能發汗的情況又有表證時應該怎麼辦?就用「小建中湯加黃耆」,黃耆可以固表補氣,讓三焦通道暢通,屬於氣藥,走表,目的就是減少發汗,先把裡扶正而發一點表。
Thumbnail
作為溝通社團的一員,其實我原本以為自己在裡頭的定位會是像年輕時一樣是個激進份子,但1124的結果令我的心態轉變了不少。不論是看待社運、看待政治的操作與許多人口中的「政治酬庸」,我以前宛如「左膠」般的鋒利被磨平,逐漸把自己的思想核心拉回到左與右的中心,也就是為自己的政治意念取得平衡。