【編者按】 給程式設計師寫範疇論聽上去是一件瘋狂的事情,但 Bartosz Milewski 就這麼做了。今天為大家分享的是小夥伴 @garfileo 翻譯自 Bartosz Milewski 的《Category Theory for Programmers》序部分,接下來還會為大家帶來《複合的本質》、《類型與函數》等文章。
以下是序部分的翻譯內容。
我打算為程式設計師們寫一本講範疇論的書已經有一段時間了。注意,受眾不是計算機科學家,而是程序猿——是工程師,而不是科學家。這聽起來挺瘋狂,我也有些誠惶誠恐,但是我無法容忍科學與工程之間存在著巨大的鴻溝,更何況我自身的工作也是經常需要我在這兩個世界中穿梭。不過,要解釋一些東西,總讓我感覺非常窘迫。我非常敬仰 Richard Feynman(理察·費恩曼),在講授知識方面他是深入淺出的大師。我不是 Feynman,但我會盡力。我從發布這篇序言開始,激勵讀者學習範疇論,希望能引發一些討論並得到一些反饋意見。
下面我要用幾段文字讓你相信,這本書是寫給你的。根本沒必要擔心它是幾乎會耗盡你所有的業餘時間的一門最抽象的數學。
我的樂觀來自一些觀察。首先,範疇論是相當有用的編程思想寶藏。Haskell 程式設計師們已經涉足此境很久了,其中的一些思想正慢慢的滲入其他語言,只是這一過程是非常緩慢而已,我們需要使之加速。
其次,有許多種數學,它們面向不同受眾。你可能不喜歡代數學,但這並不意味這你無法喜歡範疇論。我會向你展示,範疇論非常適合程序猿的思維。因為範疇論處理的對象不是計算細節,而是結構。它處理的是使程序可複合的結構。
複合是範疇論的精髓,它也是範疇論自身定義的一部分。我會證明編程的本質是『複合』。我們一直都在組合一些東西,這種行為從很久以前一群偉大的工程師提出子程序的時代就開始了。很久以前,結構化編程原理掀起了編程的革命,它立足於代碼級別的複合。伴隨面向對象編程而來的則是對象的複合。函數式編程不僅僅使得函數與代數樹覺結構可以複合從而使得它們能夠實現對並發計算的支持,它還提供了其他編程範式難以支持的東西。
第三,我有秘密武器,一把庖丁之刀,我要用它將數學大卸八塊使之成為程序猿的美味佳餚。如果你是數學家,你不得不大膽假設,小心求證,嚴格的構造你的定理,然後產生令外人難以卒讀的論文與專著。我是訓練有素的物理學家,在物理學中,我們使用著並不正規的推理來取得令人激動的發現。數學家們嘲笑偉大的物理學家 P. A. M. Dirac 為求解一些微分方程而提出的狄拉克 δ 函數,但是當他們發現了一個叫做廣義函數論的新的數學分支時,他們就不笑了,因為廣義函數論只是對 Dirac 觀點的一種形式化描述。
當然,採用不嚴肅的論證方式很容易產生謬論。因此在這本書中凡是遇到不正式的論證時我會盡力確定其背後存在著相應的實際數學理論。我床頭有一本被我翻的破破爛爛的 Saunders Mac Lane 寫的《Category Theory for the Working Mathematician》。
由於這本書是寫給程式設計師的範疇論,因此我將會用電腦程式代碼展現範疇論的主要概念。你可能會擔心函數式語言會比傳統的命令式語言更接近數學,並認為前者為此已經提供了更多的抽象能力,所以想當然的認為只有學習了 Haskell 方能將範疇論的能量作用於現實,或者認為範疇論在函數式編程範式之外沒有什麼用處,這些看法並不正確。我會提供大量的 C++ 的例子,只不過你得容忍一些醜陋的語法,需要在繁瑣的代碼中探尋清晰的模式,並且在更高層抽象的場合不得不做一些複製與粘帖的工作,不過這也正是大部分 C++ 程式設計師經常幹的事。
不過,你也無法脫離 Haskell 的羈絆。雖然沒有必要成為一名 Haskell 程式設計師,但你需要將 Haskell 作為一種草圖性的語言,用於描述那些 C++ 示例的實現思想。這也正是我當初開始學習 Haskell 的所用的方法。Haskell 簡潔扼要的語法與強大的類型系統,對於理解與實現 C++ 模板、數據結構與算法非常有幫助。當然,我不可能要求讀者事先以已經了解 Haskell,我會逐步介紹 Haskell 的知識,並且會對我所用到的那部分 Haskell 代碼給出詳細的解釋。
如果你是一名有經驗的程式設計師,可能會自問:即使不懂範疇論與函數式方法,我也照樣寫代碼,似乎沒什麼必要學習它們。的確如此,不過你無法阻止正在侵入命令式語言的那股沉穩的函數式潮流。即使是 Java,面向對象編程的堅固堡壘,也拱手請來了 Lambda。C++ 也正在大踏步前進,現在每隔三五年就發布一個新標準,它正在嘗試趕上這個正在變化的世界。這一切都在為一場變革而準備,這種變革,用我們物理學家的術語可稱為相變。如果你持續的燒水,它最終會沸騰。我們現在正處於青蛙的位置,必須決定是在升溫的水中繼續遊動,還是開始作出其他抉擇。
驅動編程範式產生巨大變革的力量之一是多核革命。主流的編程範式——面向對象編程已經難以勝任並發與並行計算領域,它只會造成危險且充滿 bug 的設計。數據隱藏,是面向對象的基本前提,一旦對象被共享且被修改,就會造成數據競爭。將數據與互斥鎖組合起來看似是個不錯的解決方案,但不幸的是,互斥鎖不支持複合,並且一旦在數據競爭中出現死鎖,便非常難以調試。
對於非並發計算,軟體系統日益遞增的複雜度也正在炙烤著命令式編程範式。簡而言之,副作用正在失去控制。有副作用的函數便於理解與編寫的。原則上,有副作用的函數所產生的影響可在函數名以及注釋中予以標明。一個叫做 SetPassword 或 WriteFile 的函數顯然在修改某種狀態並產生副作用,對此我們已經非常習慣且不以為然。只有當我們開始將這些有副作用的函數層層組裝到一起,事情就開始變得棘手了。副作用本身並不壞,但是將它們塞到一個大尺度視圖中,我們很難再看清它們,因此它們也就脫離了我們的掌控。完全與副作用打交道的命令式編程範式,副作用無法剝離。
硬體的變化與軟體複雜度的增長都在迫使我們重新思考編程的根本思想。正如歐洲最宏偉的哥德式大教堂的建造者那樣,我們正在面對著原料與結構的限制而磨礪著我們的技藝。法國的博韋有一座未完工的哥德式教堂,它就是人類與限制作鬥爭的見證。這座教堂的設計企圖在高度與採光方面擊敗所有的教堂,但是建造中卻出現了一系列的崩塌。當時不得不用鋼梁木柱臨時做成支撐架構來阻止崩塌,但是於事無補,因為很多東西在設計上就是錯的。從現代的視角來看,博韋教堂是個奇蹟,其相當多的一部分哥德式結構已經成功的建造了出來,這在那個沒有現代材料科學、計算機建模、有限元分析甚至沒有普通的數學與物理的時代顯得有些不可思議。我期望我們的後代也會敬佩我們在構建複雜的作業系統、網絡伺服器以及網際網路架構中展現出來的技術。毫不客氣的說,他們理應如此,因為我們是在脆弱的理論基礎上完成的這一切。但是,如果我們想繼續前進,那麼就必須修正現有的理論基礎。
-EOF-
閱讀原文 提前 get 更多專屬程序猿的範疇論,做一個上進的程序猿。
專業的開發者技術社區
多樣化線上知識交流
豐富線下活動和給力工作機會