原文見 http://bartoszmilewski.com/20...程序員
我打算爲程序猿們寫一本講範疇論的書已經有一段時間了。注意,受衆不是計算機科學家,而是程序猿——是工程師,而不是科學家。這聽起來挺瘋狂,我也有些坐臥不安,可是我沒法容忍科學與工程之間存在着巨大的鴻溝,更況且我自身的工做也是常常須要我在這兩個世界中穿梭。不過,要解釋一些東西,總讓我感受很是窘迫。我很是敬仰 Richard Feynman(理查德·費恩曼),在講授知識方面他是深刻淺出的大師。我不是 Feynman,但我會盡力。我從發佈這篇序言開始,激勵讀者學習範疇論,但願能引起一些討論並獲得一些反饋意見。算法
下面我要用幾段文字讓你相信,這本書是寫給你的。根本不必擔憂它是幾乎會耗盡你全部的業餘時間的一門最抽象的數學。編程
個人樂觀來自一些觀察。首先,範疇論是至關有用的編程思想寶藏。Haskell 程序猿們已經涉足此境好久了,其中的一些思想正慢慢的滲入其餘語言,只是這一過程是很是緩慢而已,咱們須要使之加速。segmentfault
其次,有許多種數學,它們面向不一樣受衆。你可能不喜歡代數學,但這並不意味這你沒法喜歡範疇論。我會向你展現,範疇論很是適合程序猿的思惟。由於範疇論處理的對象不是計算細節,而是結構。它處理的是使程序可複合的結構。服務器
複合是範疇論的精髓,它也是範疇論自身定義的一部分。我會證實編程的本質是『複合』。咱們一直都在組合一些東西,這種行爲從好久之前一羣偉大的工程師提出子程序的時代就開始了。好久之前,結構化編程原理掀起了編程的革命,它立足於代碼級別的複合。伴隨面向對象編程而來的則是對象的複合。函數式編程不只僅設計函數的複合與代數數據結構,它還提供了對併發計算的支持,這是其餘編程範式難以實現的。網絡
第三,我有祕密武器,一把庖丁之刀,我要用它將數學大卸八塊使之成爲程序猿的美味佳餚。若是你是數學家,你不得不大膽假設,當心求證,嚴格的構造你的定理,而後產生令外人難以卒讀的論文與專著。我是訓練有素的物理學家,在物理學中,咱們使用着並不正規的推理來取得使人激動的發現。數學家們嘲笑偉大的物理學家 P. A. M. Dirac 爲求解一些微分方程而提出的狄拉克 δ 函數,可是當他們發現了一個叫作廣義函數論的新的數學分支時,他們就不笑了,由於廣義函數論只是對 Dirac 觀點的一種形式化描述。數據結構
固然,採用不嚴肅的論證方式很容易產生謬論。所以在這本書中凡是遇到不正式的論證時我會盡力肯定其背後存在着相應的實際數學理論。我牀頭有一本被我翻的破破爛爛的 Saunders Mac Lane 寫的《Category Theory for the Working Mathematician》。架構
譯註: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
的函數顯然在修改某種狀態併產生反作用,對此咱們已經很是習慣且不覺得然。只有當咱們開始將這些有反作用的函數層層組裝到一塊兒,事情纔開始變得棘手。反作用自己並不壞,可是將它們塞到一個大尺度視圖中,咱們很難再看清它們,它們便脫離了咱們的掌控。徹底與反作用打交道的命令式編程範式纔是元兇。
硬件的變化與軟件複雜度的增加都在迫使咱們從新思考編程的根本思想。正如歐洲最宏偉的哥特式大教堂的建造者那樣,咱們正在面對着原料與結構的限制而磨礪着咱們的技藝。法國的博韋有一座未完工的哥特式教堂,它就是人類與限制做鬥爭的見證。這座教堂的設計企圖在高度與採光方面擊敗全部的教堂,可是建造中卻出現了一系列的崩塌。當時不得不用鋼樑木柱臨時作成支撐架構來阻止崩塌,但於事無補,由於不少東西在設計上就是錯的。從現代的視角來看,博韋教堂是個奇蹟,其至關多的一部分哥特式結構已經成功的建造了出來,這在那個沒有現代材料科學、計算機建模、有限元分析甚至沒有普通的數學與物理的時代顯得有些難以想象。我指望咱們的後代也會敬佩咱們在構建複雜的操做系統、網絡服務器以及互聯網架構中展示出來的技術。絕不客氣的說,他們理應如此,由於咱們是在脆弱的理論基礎上完成的這一切。可是,若是咱們想繼續前進,那麼就必須修正現有的理論基礎。
下一篇 -> 範疇:複合的本質