目前幾乎主流語言都或多或少提供 FP,但由於各語言有各自包袱,因此都只能提供妥協後方案,初學者卻很難發現其 FP 精神;也由於 Imperative 與 OOP 寫法仍保留,很容易不知不覺又使用 Imperatve 與 OOP 思考,因此我們需要一個 Pure Functional 語言重新格式化腦袋。
Version
Haskell for Mac 1.8.2
GHC 8.6.4
Multi-paradigm Language
現在主流語言幾乎 multi-paradigm,以個人工作上用過的語言為例:C++、PHP、C#、ECMAScript、F# 都或多或少提供 FP 能力:
- C++、C#、PHP:以 Imperative 與 OOP 為基礎擴充語言支援 FP,如 C# 的 FP 就是以 OOP 模擬而成
- ECMAScript:是個 7 分 FP,2 分 OOP 與 1 分 Imperative 的奇特語言,不過大部分人卻只使用其只有 1 分的 imperative,而其 OOP 亦使用 FP 加以模擬,但 ECMAScript 卻是本質上最接近 FP 的主流語言
- **F#**:非常接近完整 FP,但亦提供 Imperative 與 OOP 支援,只可惜 F# 並非主流語言
PHP、CSharp
我個人曾經在 PHP 與 C# 學習 FP,但效果都不好,主要是 PHP 與 C# 本身 Imperative 與 OOP 包袱太重,擴充支援的 FP 很不直覺,常會有明明 PHP 與 C# 本身 Imperative 與 OOP 已經很好用,為什麼要砸自己的腳學習奇怪 FP 的感覺。
FSharp
F# 是我第一個 FP 啟蒙語言,F# 支援 immutable、first-class function、curried function、partial application、higher-order funtion、point-free、pipeline 、function composition、option、pattern matching 等眾多 FP 代表性功能,且 FP 語法非常精簡直覺,可讀性亦高,唯一缺點是 F# 仍支援 Imperative 與 OOP,因此不算 Pure FP,只能算 functional-first,且 F# 亦不算主流語言,實用性不高。
ECMAScript
由於 F# 打通了我 FP 任督二脈,讓我以完全不同角度看待曾經很鄙視的 ECMAScript,其實 ECMAScript 已支援 first-class function、closure、arrow function、IIFE、higher-order function,而 curried function 亦可使用 arrow function 實現,也能透過 Ramda 輔助支援 partial application、point-free、function pipeline 與 function composition、lens … 等,已經算是 準 FP 語言
,且 ECMAScript 無論前端後端都能使用,實用性超高。
ECMAScript 雖然是準 FP 語言,但仍有其不足之處,如缺乏 immutable、maybe、algebraic data type 、pattern matching …等,雖然都可透過 library 補全,但畢竟不是原生支援,syntax 沒那麼直覺漂亮,學習起來效果也沒那麼直覺。
此外一些 algebraic data type (如 functor、monad、monoid … 等) 應用,在 ECMAScript 生態圈也不容易學習,最後還是要求助於 Pure FP 生態圈。
Haskell
一直到我遇到 Haskell,一個 Pure FP,才發現我之前走了太多彎路了。
Haskell 是一個完全以 FP 設計的語言,有四個很了不起特色:
- Everything is immutable
- Everything is expression
- Everything is function
- Pure functional language
Everything is Immutable
由於 immutable 無法修改 variable,我們被逼的將修改 variable 的任務切割成眾多小任務而造就 pure function,在重構階段發現重複而抽出 higher-order function,最後再以 function composition 收工,可發現 immutable 是 pure function、higher-order function 與 function composition 的催化劑,這只有在 Pure FP 才能體會,在 multi-paradigm 語言因為有太多解法,不見得會走 Pure FP 這條路。
Everything is Expression
ECMAScript 就是個典型 statement 與 expression 混合語言,statement 適合 Imperative,而 expression 適合 Functional,也因為 ECMAScript 支援 statement,這開啟了大部分人以 Imperative 使用 ECMAScript 之門,這只發揮了其 10% 功力;而 Pure FP 只有 expression,可讓我們專心以 FP 解決問題。
Everything is Function
多半 multi-paradigm 語言是 class 與 function 並存,ECMAScript 2015 也漸漸補齊 class 該有功能,F# 也是 function 與 type 兼具,而 Haskell 只有 function,可讓我們專心以 FP 解決問題。
Pure Functional Language
也由於 Haskell 是完整 FP 語言,沒有 Imperative 與 OOP 包袱,處處以 FP 設計,也不必再像 ECMAScript 求助於大量 library,在 Haskell 原生 syntax 就能感受到 FP 強大威力,非常適合用來學習 FP。
Conclusion
- Multi-paradigm 語言的優點是廣納百川,讓你在解決問題有多種武器,但缺點是由於解決問題方法太多,並不適合學習特定 paradigm;反之 single-paradigm 語言由於 syntax 明確乾淨沒有包袱,有助於專心學習該 paradigm
- 學習程式語言不見的都要以實用角度出發,若一個語言能讓你改變思考方式,是一個新的 paradigm,那就值得學習;反之若 paradigm 相同,只是 syntax 不同而已,就不必浪費時間了
- Haskell 能讓我們大腦練習全新 paradigm,但也不用擔心 Haskell 實用性不高,因為我們可藉由 Haskell 學習純 FP 思考,日後再以 ECMAScript 實現