iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0

https://ithelp.ithome.com.tw/upload/images/20250831/20118113BLkCodRJyL.png
終於到了鐵人賽的最後一天了,好好回顧這三十天的歷程和內容。

起程FP-TS

一開始會選擇fp-ts當作函數式程式設計的起點當然是因為從事網頁的開發,當對函數式程式設計和fp-ts函式庫進行了解後發現,其實typescript搭配fp-ts在函數式程式設計的實現度也滿高。首先當然是typecript(javascript)支援高階函數(HOF)和箭頭函數(Arrow Function),讓符號和使用都和專替HP設計的Haskell極為相似;再來是typescript提供的型別檢查和泛型也讓一些型別空間的建構也有幾分Haskell的味道。最後是javascript陣列內建的許多方法,基本上就是取法於函數式程式設計,也具有宣告式程式風格的意義。很明顯的,Javascript在發展的過程式吸取了不少FP的設計。

當然,相對於專為函數式程式設計的Haskell語言,typescript + fp-ts,還是有許多不足的地方,其一是javascript無法使用中序函數(infix function)的寫法,也沒有內建的合成函數(compose的寫法)。這讓我們的函數「接管」的寫法會變成由上而下,不若Haskell由右而左,這讓程式的閱讀線的流向是由上而下,頁面比較長,必須常常上下翻頁。當然這是因為javascript的運算式和函數還是不同的東西,函數的合成如果不採用pipe函數而直接用f(g(x))的方式合成,當合成的層次多了,括號會變得太多,影響程式的閱讀。關於無法使用中序函數,個人覺得函數的鏈接形式可以達成有部分中序函數味道。

總之,javascript做為前端網頁的唯一語言,而typescript也已廣泛為前端開發者接受,fp-ts是目前實現函數式程式設計較高的函式庫。不過,也正由於fp-ts的高度實現函數式程式設計高度抽象化的特色,讓程式碼比較不直觀,而造成學習曲線過於陡峭,推廣不易,造成fp-ts不少的挑戰,這也是我寫這一系列的動機之一。目前作者已經宣布fp-ts正式和Effect-TS生態系合併,未來的Effect-TS將被視為fp-ts的接續者或者當作fp-ts 3.0的體現。

轉合Haskell

如果要百分之百感受函數式程式設計的威力,最好是使用專替FP(Functional Programming)設計的語言,目前流行度最高的FP語言便是Haskell,這邊就個人的體驗提出一些來與大家分享。

  • 資料流由右而左。由於函數可以不用括號,柯里化和沒有柯里化的寫法並沒有差別(Haskell的所有函數都是柯里化),而函數的合成也使用和數學上相近的符號「句點.」,因為f . g x即代表f ∘ g(x) = f(g(x)),這可以讓我們閱讀視線由右而左(這也符合數學上的習慣),因此一行程式碼便可以有相當強大的功能。
  • 運算符就是函數。Haskell支援中序函數的寫法(infix function expression),因此運處符號和函數是沒有區分的,一切都是函數。例如:+ 也是一個函數,5 + 3和 + 5 3是一樣的,因此有時候會有一些極抽象的式子,例如你要將一個陣列的數字和加總,只要寫 foldl (+) 0,因為foldl就是reduce,(+)就是Haskell內建的sum函數,不用再自行定義,0是初始值。另外,一些Monad相關的函數也是用符號代替,例如ap函數用<*>,infix map 則用<$> ,bind函數也用>>=來表示,使得資料流讀起來更順暢,而在Do notation中,輸出入(IO monad)的程式碼和傳統程式極為相似。
  • 高階類別支援與型別推論。因為非常強大的型別推論能力和高階類別的支援,一些跨類別的函數使用非常方便,例如fmap可以用在任何Functor類別上,無須指定那一個型別建構子。一個函數只要明確說明有那些類別限制,只要是滿足型別限制的型別便可應用此函數,有極高的抽象化。

Do Notation

在知學Haskell程式時,main程式中的Do Notation是最困難,我們直接看一個Haskell quickSort的程式風格。

-- Use the standard Data.List module for the partition function
import Data.List (partition)

-- Quicksort implementation
import Data.List (partition)

-- Quicksort implementation
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort (p:xs) = quicksort smaller ++ [p] ++ quicksort larger
  where
    (smaller, larger) = partition (< p) xs

-- Main function for user interaction
main :: IO ()
main = do
  putStrLn "Enter numbers separated by spaces:"
  input <- getLine
  let sortedNumbers = quicksort $ map read (words input) :: [Int]
  putStr "The sorted list is: "
  print sortedNumbers

這個程式在main = do這一行開始,看起來很像一般的程式語言,但是對<-確會覺得很彆扭,為何它不用=,主要的原因是,它其實是巢狀bind函數的語法糖,類似Javascript中async/await的語法角色。

Haskell的bind(>>=)函數其實就是我們的chain(flatMap)函數,只是參數的順序有所不同,而且bind(>>=)用的是中序函數的寫法,也就是說x >>= f 和chain(f)(x)一樣,如果f用Haskell的Lambda函數(相當於Javascript的匿名函數)\x -> return(x + 1),return則相當於fp-ts中的IO.of,所以fp-ts中的程式碼

const main = pipe(
    IO.of(3),
    IO.chain(x => pipe(
        IO.of(4),
        IO.chain(y => pipe(
            IO.of(5),
            IO.chain(z => IO.of(x + y +z))
        ))
    ))
)
main()

在Haskell中變成

main = return 3 >>= (\x -> 
          return 4 >>= (\y -> 
          return 5 >>= (\z -> 
          return x + y + z)))

如果寫成Do Notation則變成

main :: IO Int
main = Do
    x <- 3
    y <- 4
    z <- 5
    return x + y + z

所以在Haskell IO 的 Do Notation中,最後一個return會保留,而且不能bind任何東西。而let後面的=必須接一般的型別,不能是IO Action。其實Do Notation可以用在任何的Monad之中,不限於IO Monad,只是IO Monad的main函數通常會用Do Notion,Haskell也會自動執行main函數。這種語法糖相當Javascript非同步回呼地獄(callback hell)由async/await的概念,以上是對Haskell Do Notation用我們fp-ts的理解做簡單的說明。

「水能載舟,也能覆舟」,也正因為這些優點,Haskell是一種極度抽象化的語言,初學的學習曲線極,所以語言的使用推廣不易,是一個小眾市場,但是對追求程式碼極簡化的開發者,卻值得玩一玩,希望有興趣親自去嚐試,畢竟上面三點只是我以個人觀點寫出,凡事要親自體驗才是實在。

付出與收穫

這是第二次參加鐵人賽,上次在最後階段每天想主題、趕程式和寫文稿中渡過,常常在前二天還沒決定要做什麼,最後完成的發文總覺得不是很完美;這一天比上次提前更早時間準備,也事先將內容主題設定好,存貨也都準備了一些,但是到了最後階段,還是改了不少主題,一些事先準備的素材也就用不上,最後幾十天還是趕了一些,幸好還是順利完成。

雖然有些主題準備的倉促,事先也沒先研究好,從搜集資料到程式撰寫還有發文都沒有把握,一度放棄新主題,幸好後來堅持完成,也對新的主題有更深入的了解,這真的是這次鐵人賽很大的收穫;如果沒有參加鐵人賽應該不會接觸這些主題。

由於許多的名詞和術語並沒有統一的中文翻譯,加上兩岸使用的名詞在網路的世界常常摻混,因為一開始還沒有統整,常在不同日期的發文使用不同的中文,感到非常困擾。幸好最後找到統整的表達方式,也將不同日期的發文重新統整發表,希望閱讀起來不會有太大誤會。

總而言之,參加鐵人賽,收穫的永遠是比付出的多,關於今年鐵人賽的發文,有時間還是會持續修訂或增加內容,也會持續的發文相關的主題,今年就在這裏和所有閱讀的讀者再見。


上一篇
Day 29. 單元測試 - Vitest
系列文
數學老師學函數式程式設計 - 以fp-ts啟航30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言