王垠:從工具的奴隸到工具的主人

發表於2012-09-11

來源:王垠的部落格

我們每個人都是工具的奴隸。隨著我們的學習,我們不斷的加深自己對工具的認識,從而從它們裡面解脫出來。現在我就來說一下我作為各種工具的奴隸,以及逐漸擺脫它們的“思想控制”的歷史吧。

當我高中畢業進入大學計算機系的時候,輔導員對我們說:“你們不要只學書本知識,也要多見識一下業界的動態,比如去電腦城看看人家怎麼裝機。”當然他說我們要多動手,多長見識,這是對的。不過如果成天就研究怎麼“裝機”,研究哪種主機板配哪種 CPU 之類的東西,你恐怕以後就只有去電腦城賣電腦了。

本科的時候,我經常發現一些同學不來上數學課。後來卻發現他們在宿舍自己寫程式,對 MFC 之類的東西津津樂道,引以為豪。當然會用 MFC 沒有什麼不好,可是如果你完全沉迷於這些東西,恐怕就完全侷限於 Windows 的一些表面現象了。

所以我在大學的時候就開始折騰 Linux,因為它貌似讓我能夠“深入”到計算機內部。那個時候,書店裡只有一本 Linux 的書,封面非常簡陋。這是一本非常古老的書,它教的是怎樣得到 Slackware Linux,然後把它從二三十張軟盤裝到電腦上。總之,我就是這樣開始使用 Linux 的。後來我就走火入魔了,有時候上課居然在看 GCC 的內部結構文件。後來我又開始折騰 TeX,把 TeXbook 都看了兩遍,恁是用它寫了我的本科畢業論文。

後來進了清華,因為不滿意有人嘲笑我用 Linux 這種“像 DOS 的東西”,以及國內網站都對 Windows 和 IE 進行“優化”的情況,就寫了個“完全用 Linux 工作”。確實,會 Linux 的人現在更容易找到工作,更容易被人當成高手。但是那些工具同樣的奴役了我,經常以一些雕蟲小技而自豪,讓我看不到如何才能設計出新的,更好的東西。當它們的設計改變的時候,我就會像奴隸一樣被牽著鼻子走。

這也許就是為什麼我在清華的圖書館發現 《SICP》 的時候如此的欣喜。那本書是嶄新的,後面的借書記錄幾乎是空白的。這些看似簡單的東西教會我的,卻比那些大部頭和各種 HOWTO 教會我的更多,因為它們教會我的是 WHY,而不只是 HOW。當時我就發現,雖然自認為是一個“資深”的研究生,學過那麼多種程式語言,各種系統工具甚至核心實現,可是相對於 SICP 的認識深度,我其實幾乎完全不會寫程式!在第三章,SICP 教會了我如何實現一個物件導向系統。這是我第一次感覺到自己真正的在開始認識和控制自己所用的工具。

因為通常人們認為 Scheme 不是一個“實用”的語言,沒有很多“庫”可以用,效率也不高,而 Common Lisp 是“工業標準”,再加上 Paul Graham 文章的慫恿,所以我就開始瞭解 Common Lisp。在那段時間,我看了 Paul Graham 的 《On Lisp》 和 Peter Norvig 的 《Paradigms of Artificial Intelligence Programming》。怎麼說呢?當時我以為自己學到很多,可是現在看來,它們教會我的並沒有 《SICP》 的東西那麼精髓和深刻。開頭以為一山還有一山高,最後回頭望去,其實複雜的東西並不比簡單的好。現在當我再看 Paul Graham 和 Peter Norvig 的文章,就覺得相當幼稚了,而且有很大的宗教成分。

scheme

 

進入 Cornell 之後,因為 Cornell 的程式語言課是用 SML 的,我才真正的開始學習“靜態型別”的函式式語言。之前在清華的時候,有個同學建議我試試 ML 和 Haskell,可是因為我對 Lisp 的執著,把他的話當成了耳邊風。當然現在用上 SML 就免不了發現 ML 的型別系統的一些撓人的問題,所以我就開始瞭解 Haskell,並且由於它看似優美的設計,我把“終極語言”的希望寄託於它。我開始著迷一些像 monads, type class, lazy evaluation 一類的東西,看 Simon Peyton Jones 的一些關於函式式語言編譯器的書。以至於走火入魔,對其它一切“常規”語言都持鄙視態度,看到什麼都說“那隻不過是個 monad”。雖然有些語言被鄙視是合理的,有些卻是被錯怪了的。後來我也發現 monad, type class, lazy evaluation 這些東西其實並不是什麼包治百病的靈丹妙藥。

但是我很不喜歡 Cornell 的壓抑氣氛,所以最後決定離開。在不知何去何從的時候,我發了一封 email 給曾經給過我 fellowship 的 IU 教授 Doug Hofstadter (《GEB》的作者)。我說我不知道該怎麼辦,後悔來了 Cornell,我現在對函式式語言感興趣。他跟我說,IU 的 Dan Friedman 就是做函式式語言的啊,你跟他聯絡一下,就說是我介紹你來的。我開頭看過一點 The Little Schemer,跟小人書似的,所以還以為 Friedman 是個年輕小夥。當我聯絡上 Friedman 的時候,他貌似早就認識我了一樣。他說當年你的申請材料非常 impressive,可惜你最後沒有選擇我們。你要知道,世界上最重要的不是名氣,而是找到賞識你,能夠跟你融洽共事的人。你的材料都還在,我會請委員會重新考慮你的申請。IU 的名氣實在不大,而 Friedman 實在是太謙虛了,所以連跟他打電話都沒有明確表態想來 IU,只是說“我考慮一下……”這就是我怎麼進入 IU 的。

Friedman 的教學真的有一手。雖然每個人對他看法不同,但是有幾個最重要的地方他的指點是幫了我大忙的。有人可能想象不到,在 Scheme 這種動態型別語言的“老槽”,其實有人對“靜態型別系統”的理解如此深刻。也就是在 Friedman 的指點下,我發現型別推導系統不過是一種“抽象解釋”,而各種所謂的“typing rule”,不過是抽象直譯器裡面的分支語句。我後來就通過這個“直覺”,再加上 Friedman 的邏輯語言 miniKanren 裡面對邏輯變數和 unification 的實現,做出了一個 Hindley-Milner 型別推導系統(HM 系統),也就是 ML 和 Haskell 的型別系統。雖然我在 Cornell 的課程作業裡實現過一個 HM 系統,但是直到 Friedman 的提點,我才明白了它“為什麼”是那個樣子,以至於達到更加優美的實現。後來經他一句話點撥,我又寫出了一個 lazy evaluation 的直譯器(也就是 Haskell 的語義),才發現原來 SPJ 的書裡所謂的“graph reduction”,不過就是如此簡單的思想。只不過在 SPJ 的書裡,細節掩蓋了本質。後來我在之前的 HM 系統之上做了一個非常小的改動,就實現了 type class 的功能,並且比 Haskell 的實現更加靈活。所以,就此我基本上掌握了 ML 和 Haskell 的理論精髓。

可是型別系統卻貌似一個無止境的東西。在 ML 的系統之上,還有 System F,Fw, MLF,Martin Lof Type Theory,CIC,…… 怎麼沒完沒了?我一直覺得這些東西過度複雜,有那個必要嗎?直到 Amal Ahmed 來到 IU,我才相信了自己的感覺。然而,這卻是以一種“反面”的方式達到的。

Amal 是著名的 Andrew Appel (“虎書”的作者)的學生,在型別系統和編譯器的邏輯驗證方面做過很多工作。可是她比較讓人受不了,她總是顯得好像自己是這裡唯一懂得型別的人,而其他人都是型別白痴。她不時的提到跟 Bob Harper, Benjamin Pierce 等型別大牛一起合作的事情。如果你問她什麼問題,她經常會回答你:“Bob Harper 說……”她提到一個術語的時候總是把它說得無比神奇,把它的提出者的名字叫得異常響亮。有一次她上課給我們講 System F,我問她,為什麼這個系統有兩個“binder”,貌似太複雜了,為什麼不能只用一個?她沒有正面回答,而是嘲諷似的說:“不是你說可以就可以的。它就是這個樣子的。”後來我卻發現其實有另外一個系統,它只有一個 binder,而且設計得更加簡潔。後來我又在課程的 mailing list 問了一個問題,質疑一個編譯器驗證方面的概念。本來是純粹的學術討論,卻發現這封 email 根本沒有發到全班同學信箱裡,被 Amal 給 moderate 掉了!

看到這種種詭異的行為,我才意識到原來學術界存在各種“幫派”。即使一些人的理論完全被更簡單的理論超越,他們也會為“自己人”的理論說話,讓你搞不清到底什麼好,什麼不好。所以後來我對一些型別系統,以及 Hoare Logic 一類的“程式邏輯”產生了懷疑。我的課程 project 報告,就是指出 Hoare Logic 和 Separation Logic 所能完成的功能,其實用“符號執行”或者 “model checking” 就能完成。而這些程式邏輯所做的事情,不過是把程式翻譯成了等價的邏輯表示式而已。到時候你要得知這些邏輯表示式的真偽,又必須經過一個類似程式分析的過程,所以這些邏輯只不過讓你白走了一些彎路。當 Amal 聽完我的報告,勉強的笑著說:“你告訴了我們這個結論,可是你能用它來做什麼呢?”我才發現原來透徹的看法,並不一定能帶來認同。人們都太喜歡“發明”東西,卻不喜歡“歸併”和“簡化”東西。

可是這型別系統的迷霧卻始終沒有散去,像一座大山壓在我頭上。我不滿意 Haskell 和 ML 的型別系統,又覺得 System F 等過於複雜。可是由於它們的“理論性”和它們創造者的“權威”,我不敢斷定自己的看法就不是偏頗的。對付疑惑和恐懼的辦法就是面對它們,看透它們,消滅它們。於是,我利用一個 independent study 的時間,獨立實現了一個型別系統。我試圖讓它極度的簡單,卻又“包羅永珍”。經過一番努力,這個型別系統“涵蓋”了 System F, MLF 以及另外一些類似系統的推導功能,卻不直接“實現”他們。後來我就開始試圖讓它涵蓋一種非常強大的型別系統,叫做 intersection types。這種型別系統的研究已經進行了 20 多年,它不需要程式設計師寫任何型別標記,卻可以給任何“停機”的程式以型別。著名的 Benjamin Pierce 當年的博士論文,就是有關 intersection types 的。沒幾天,我就對自己的系統稍作改動,讓它涵蓋了一種最強大的 intersection type 系統(System I)的所有功能。然而我卻很快發現這個系統是不能實用的,因為它在進行型別推導的時候相當於是在執行這個程式,這樣型別推導的計算複雜度就會跟這個程式一樣。這肯定是完全不能接受的。後來我才發現,原來已經有人指出了 System I 的這個問題。但是由於我事先實現了這個系統,所以我直接的看到了這個結論,而不需要通過繁瑣的證明。

所以,我對型別推導的探索就這樣到達了一個終點。我的型別系統是如此的簡單,以至於我看到了型別推導的本質,而不需要記住複雜的符號和推理規則。我的系統在去掉了 intersection type 之後,仍然比 System F 和 MLF 都要強大。我也看到了 Hindley-Milner 系統裡面的一個嚴重問題,它導致了這幾十年來很多對於相關型別系統的研究,其實是在解決一個根本不存在的問題。而自動定理證明的研究者們,卻直接的“繞過”了這個問題。這也就是我為什麼開始對自動定理證明開始感興趣。

後來對自動定理證明, Partial Evaluation 和 supercompilation 的探索,讓我看到那些看似高深的 Martin Lof Type Theory, Linear Logic 等概念,其實不過也就是用不同的說法來重複相同的話題。具體的內容我現在還不想談,但是我清楚的看到在“形式化”的美麗外衣下,其實有很多等價的,重複的,無聊的東西。與其繼續“鑽研”它們,反覆的叨咕差不多的內容,還不如用它們的“精髓”來做點有用的事情。

所以到現在,我已經基本上擺脫了幾乎所有程式語言,編譯器,型別系統,作業系統,邏輯推理系統給我設定的思維障礙。它們對我來說不再是什麼神物,它們的設計者對我來說也不再是高不可攀的權威。我很開心,經過這段漫長的探索,讓我自己的思想得到了解放,翻身成為了這些工具的主人。雖然我看到某些理論工具的研究恐怕早就已經到達路的盡頭,然而它們裡面隱含的美卻是無價和永恆的。這種美讓我對這個世界的許多其它方面有了煥然一新的看法。一個工具的價值不在於它自己,而在於你如何利用它創造出對人有益的東西,以及如何讓更多的人掌握它。這就是我打算現在去做的。

 

 

本文由@唐尤華 推薦。除投稿之外,伯樂線上也歡迎各位朋友推薦閱讀後有收穫的文章。推薦方式:私信至@伯樂線上官方微博  或發郵件至webmaster#jobbole.com 。

 

相關文章