Haskell 不適用於生產環境嗎?
最近對 Haskell 產生了濃厚的興趣,準備作為自己的業餘愛好語言,並打算運用到自己在做的項目中去!但是朋友都說這個語言屬於學院派體系,是類 Scheme 的純理論語言,實際工程中壓根兒用不上!請問,現在是否有運行的不錯的 Haskell 程序,Haskell 是否適合做數據分析或者分散式運算?
以大部分人的自學能力與努力程度根本達不到能用Haskell生產級別,更何況用中文學習Haskell障礙多多,這堆人頂多算是聽說過或者懂些皮毛。用Haskell你先得會用IO吧?會用IO就得知道大約Monad是個什麼東西,想了解Monad你得先知道Applicative是啥玩意?Applicative又基於Functor。這堆東西搞懂了才是個開始而已。有個朋友跟他的同事提過,RankNType都不懂還說自己會Haskell?
Haskell能幹嘛?
函數式編程杭州分享會20150718-喻昌遠 Haskell做嵌入式開發Haskell 的商業使用Facebook如何使用Haskell處理垃圾郵件 Haskell在Facebook的使用
https://vimeo.com/12849320 Google Ganeti有沒有運行得不錯的Haskell程序?GHC、Pugs、Shake、Yesod、Pandoc、Mu、XMonad。haskell是否適合做數據分析或者分散式運算?Haskell做數據分析的書有3本,見OReilly Search: Haskell datahaskell 在語言設計,性能,編譯器質量,編程工具等等方面都是最高水平
生態環境雖比不上前10大熱門語言,但也遠遠超越其他函數式語言
從這點上來說,把haskell用在商業項目中絕對沒有任何問題
但很多haskell粉絲卻沒有把haskell用在自己的工作中
為什麼?
除了公司和客戶要求等等客觀原因外,我認為很重要的一點是haskell粉絲普遍的一種心態:追求極致,追求完美
用haskell寫東西,永遠覺得自己寫得不夠好——
能不能用惰性求值來控制計算過程?怎樣用依賴類型增加程序可靠性?這個問題有沒有純函數的解法?怎麼做成組合子dsl的形式?能不能做fusion優化?……用haskell,你沒法接受快糙猛,haskell給了程序員太多的可能性,而美是haskell社區文化的核心價值觀
所以reddit上常常會出現一個主題下幾十個貼子去反覆雕琢一個2,3行的程序
所以,除非你能過自己心理那關,亦或者已經是haskell頂級高手,否則haskell不適合寫要求快速出貨的商業程序,haskell適合搞業餘開源的東西,慢慢磨,出精品
要想快糙猛,要麼逼著自己使用haskell的一個子集,要麼直接用ocaml。雖然比起haskell,ocaml實在太過簡陋,簡陋到你沒有空間去施展做不同形式的程序,然而這卻是它的優點。方法就一個,路就一條,做起來雖然繁複(相比haskell),但你從此不用去糾結和思考程序形式,可以集中精力解決問題本身了
翻牆,股溝一下 XMonad,這個是比較流行的Linux windows manager
我渣的應用,可以在股溝上查 Google tech talk Standard Chartered.JP Morgan也有類似的應用系統
金融界的應用面主要對複雜的結構化金融產品另外,聽說廣州也有人在用,還在招人,工作問題應該不大。
=====FGX=====
其實問題就等於問,手術刀能切肉嘛?
我說,可以啊,各大醫院外科醫生每天都用手術刀切人肉。
然而,會有些豬肉佬跳來說,不對啊,我用手術刀切不了豬肉,這刀不好使,不能切肉,還是我的劏豬刀好用。
然後大家就明白了,哦,手術刀不能切肉。
結論: Haskell 適用於特定的領域問題
背景介紹: 我現在天天寫 FP (OCaml 和 Haskell 很像的一門語言), 碩士畢業第一份工作,待遇比工作經驗相同的FG好很多. 更關鍵是做自己喜歡的事情 自己的工作也開源了(GitHub - bloomberg/bucklescript: A backend for the OCaml compiler which emits JavaScript.) 本人研究生階段研究過PL(包擴Haskell,做過Haskell研究生課的助教), 但因為很久沒碰過Haskell了 可能一些術語會記錯, 然後中英文夾雜是因為我當時接觸的都是英文資料,不知道對應的中文術語.Haskell 作為帶類型的函數語言具有很明顯的優勢: global type inference, algebraic data type, nested pattern match -- 這三點是最實際生產中最實用的feature了,Haskell還有很多很甜的語法糖 像Generics, type class. Higher kind types 和 type class 合在一起使得一些抽象很好用,在這一點上沒有其他語言(我所了解的語言里)比它更expressive 了.
Haskell 比較適合的領域:數據處理, 符號計算,編譯器。其中數據處理是一個非常general 的範疇,而在Haskell里你只要定義了數據類型, 很多函數都可以自帶deriving + pattern match 非常舒服。因為Haskell是一門純語言(effect 是被編譯器標記過的),做得優化可以非常agressive, 象stream fusing, rewrite rules, Haskell 的編譯器再帶的inliner 質量非常高, inliner 是優化中非常重要的一環 (OCaml 最近也在做這個事情叫flambda).
為什麼說Haskell 只適用於一類領域呢,因為Haskell有兩個feature, laziness 和 purity.
laziness 是一個leaky abstraction, 基本上得讀源代碼才能分析一個函數的複雜度,基本上任何一個大型的Haskell程序都或多或少會有memory leak. (當然laziness 也有一些好處 這裡就不說了)
然後purity 引入了很多只有Haskell 這個語言才會有的問題,更關鍵的時很多核心演算法本質上就是imperative的,Haskell自身也能做imperative 的操作, 但是非常彆扭,還有很大一類演算法 是local 的 mutable的 但是介面是functional的 這一類演算法很難用Haskell來描述。因為Haskell非常高階的優化,很多性能很難分析,很難知道哪裡會allocation.
--- 小廣告 ---
其實現在函數式很多觀念已經進入主流語言了, 像Javascript, Mathematica, Swift, F# 都是函數式語言(個人認為Scala是OO的),除了我們公司在用OCaml, Janestreet基本上所有的都是OCaml, Facebook用OCaml的非常多.
很多很有名的軟體都是OCaml寫的, 如 Rust 編譯器(最早版本), ES4 Reference implementation(可能是SML, OCaml的近親), WebAssembly reference implementation, Flow, infer, Hack (Facebook的朋友跟我share 他們的所有php代碼都轉成hack了, 我跟FB react的發明人是好朋友,他也在FB內部幫助推廣OCaml)等等。OCaml 當時還是LLVM 唯一自帶的官方binding, 希望國內更多的人能在生產中用到FP!
編輯: 修改了一些typo實名反對樓上說使用 Haskell 是為了 「清爽簡潔」 / 「乾淨漂亮" 的答主。Haskell 的特點之一是 「清爽簡潔」 / 「乾淨漂亮" 是沒錯,但是工程上絕對不會因為這種毫無卵用的特點來決定使用或者不使用某樣語言,因為這本身就是本末倒置。
==========================================================所謂工程,就是綜合考慮各方面因素的前提下所作出的妥協。
Haskell 這類純函數語言的牛逼之處在於 靜態類型 + 純函數式。他用一種極端嚴格的方式把副作用(非常容易產生不可控bug的東東)控制在一定範圍內,從而保證代碼的正確性。純函數語言」純「的部分,是可以嚴謹到可以用數學證明代碼的正確性的,比跑測試高到不知道哪裡去了。所以在一些極端要求正確性的場景,Haskell 幾乎是首選的。
然而對正確性要求不那麼高的場景,偶爾出幾個錯誤都沒什麼問題的場景就沒必要使用這麼嚴禁的東西了。
上面那些說 Haskell 不適用於生產環境的答主答題前都忘了加一個前提,我來給他們補全:
在他們家的生產環境下,Haskell 不適用於生產環境。==========================================================
只要寫過代碼的就沒有不被各種奇奇怪怪隱藏在深處的 運行時 bug 坑過,但是現在我告訴你有一門語言,你只要能編譯通過並且不犯邏輯錯誤,就不會有bug,你敢信么?沒錯,這就是 Haskell 。
但是:
沒有銀彈沒有銀彈沒有銀彈(真正混軟體工程的你要是不知道這句話出處,我就什麼都不想說了……)要想得到這好處,就必須付出代價。樓上樓下所說的各種 Haskell 「不適用於生產環境」 的例子,都是需要付出的代價而已。
工程考慮的是成本和回報的,但是前提是至少要把付出什麼成本得到什麼回報先搞搞清楚吧。作為一個曾經有幸參與開發過Haskell商業項目的過來人,我認為最大的問題是,招不到人,招不到人,招不到人。
從我自己的角度來看,haskell在國內無法上生產最大的問題還是找不到合適的人。
我們的pm現在反對在項目裡面用react,原因是之前項目裡面使用過,但是新接手的學不會,維護成本「太高」。
目前的現狀,pm決定開發工具/語言時是看團隊里水平最低的那個開發人員,特別時那些流動性比較大的地方。
因為國內氛圍上還是推崇多上初級程序員,通過更多人力來生產更多的代碼和bug
另外我也誠懇的說一句,雖然我學haskell有一陣子了,但是我也只是勉強應該可以應用haskell到生產。也就是說,除非團隊里其他人都比我強,不然確實不適合整個團隊切換到haskell,但是部分工具什麼的還是可以考慮。Haskell in industry至少對他們來說是適用的, 生產環境用途不少各大企業跟新創赫然在列, 我掃了一眼看, 斗膽敢說Haskell在生產環境的用途是比C++廣, 其中也有一些是Python難以做到的用例
Update : @邵成 說看這個 post-rfc/sotu.md at master · Gabriel439/post-rfc · GitHub
裡面有 Haskell 生態系統中,做各種類型任務的難易程度,(比如 MachineLearning 任務就是 Immature )
=============================
可以用,但是,真得有老司機帶。
不是什麼 Monad 的問題,那些找些最容易找的材料就可以看。問題是你想寫生產環境下的 Haskell, 一個hs 文件不加上諸如 RankNTypes, GADTs 等幾個語言擴展是不夠用的。知道那些擴展是幹什麼用的,以及一個項目要加什麼,怎麼加,得緊跟社區發展。。。。
還有哪些庫成熟可用,由於 GHC 發展太快等導致 RealWorld Haskell 有點過時之類的信息也是很重要的。
還有著名的某問題:
Prelude&> minimum [1, 2]
1Prelude&> minimum (1, 2)2感覺你寫 Python, Java的話,即便是不 follow 社區發展,自己看看文檔也能寫個 50~60分的程序。
但是 Haskell 不 follow 社區發展真是連 20分的程序都寫不出來(
順便感謝某老司機帶(
這個似乎有一個很有趣的歷史
歷史上先出現了fp,然後有了oop,最後才有過程式
但其實從封裝程度上看,應該是過程式是最原始的,所以c出現之後,掀起一陣高潮
但是很快就遇到了瓶頸,所以沒有銀彈,那這個時候腫么辦呢?回頭看,oop在那邊等著呢
於是java出現拯救世界,java之前軟體工程幾乎到了崩潰的邊緣,90%的大型項目都是失敗的
因為根本就沒有封裝,oop強調封裝,你甭管這個封裝是不是很low,反正這個封裝所有人都看懂了
於是失敗率降低到50%左右,已經很好了,然後又發展
發展到一定階段之後,發現,over engineering了
這個階段的高潮是j2ee,j2ee那個封裝叫做一個登峰造極
一個簡單的crud會被拆成6-8個人去實現
甚至有專門部署的ejb維護人員
那很多人就覺得,這個不行,瞎搞,於是就開始尋找出路
慢慢就匯聚到從java語言自身上找出路,各種框架性的嘗試都不太成功
這個時候,再回頭看,fp在那邊等著呢
那我們來看,fp面臨的問題,當初為什麼沒有使用fp
純函數,不變性,這些都好辦,但是monad肯定是一個檻
那腫么辦?我們正在摸索一種模式,就是用oop語言實現一個比較pure的fp環境
然後讓用戶只需要專心實現他的function就行了
同時不需要他使用monad,也不妨礙他幹活
現階段的想法是用java等帶有oop屬性的語言,實現該框架,猶如以前用c/c++實現jvm一樣,有些東西,比如垮平台,gc,這些java不想做,好,c/c++來實現,同樣的,fp不想做的,或者說做起來有困難的,比如io,java等帶有oop特性的語言予以實現,當然可以用scala來做,scala對於java的擴展非常像是c++對於c的擴展一樣,但是事實證明c++並不適合大規模流行,因為沒有java那麼純粹,更像是一個c和java之間的中間階段語言,用來做jvm蠻好,同理,可能scala也會成為這種中間狀態語言,但是~!從目前進展看,kotlin更接近這個狀態,coroutine太重要了,scala沒有官方的協程庫,一下子就被kotlin拉開了差距,同時java也在搞loom,所以目前看,由java來實現這個框架的概率比較大,vert.x最接近這個狀態
實現了該框架之後,希望用戶不需要使用monad一樣不妨礙他們工作,我們把monad定義成類似java的反射等特性,這些特性對於商業使用,沒有太大意義,猶如普通的java程序員,他不懂什麼是反射,不妨礙他填代碼,所以希望做到的是,用這個框架能夠營造出一種:用haskell的程序員,他不需要知道什麼是monad也不妨礙他填代碼,只要能做到這一步,那離商業推廣haskell就非常近了,你可以說他是半吊子,那這個不管,以解決問題為唯一目的
目前看,進展還不錯,這裡面的路還很長,但是大概的方向是這樣子
要實現真正商用,還需要以下幾個步驟:
- haskell要能夠運行在jvm上,這個由eta實現,同時需要周邊例如gradle等包管理工具的支持,eta目前正在做sbt和gradle的plugins
- ide支持,目前intellij idea上的haskforce已經準備支持eta了,進行中,intelli haskell其實體驗更好,但是目前還沒聽說有支持eta的說法
- 框架支持,vert.x已經表現出了足夠的興趣,scala部分表示願意幫忙,主要是codegen
說著說著感覺像是fate的故事背景,三個家族開始造萬能許願機了,以後是不是每隔那麼幾年,每個語言召喚一個英靈出來對打?
最近幾天在vert.x上實現了haskell的verticle,那過程是那麼地自然,簡直了
在這個過程中我們沒有想過monad是個什麼東東,因為vert.x的主要api都接受函數作為參數,haskell的函數又是那麼地自然,定義了那麼多函數,丟一個進去就是了
所以只要把vert.x的api直接包裝成haskell api就行了,剩下的該怎麼做就怎麼做,不管怎樣,這一切都才剛開始,會的人實在是不多,haskell,jvm和vert.x都不是那麼容易的,會的人不太多,但是千里之行,始於足下,路嘛,也是走的人多了,才有了路
haskell學習成本太高了。去年10月我開始學rust,大概用了10天時間,還是利用零散的時間。把rust網站上的書都看完了,然後也並沒有覺得有太難理解的地方。由於rust里有一些函數式編程的特性,我在十一之後開始對haskell感興趣。用了1個多月的業餘時間看完了趣學指南。然而我發現離應用還遠。第一個難題就是monad,我理解它的語法,卻不理解它的妙處,於是開始找資料看。亂起八糟看了很多範疇論的東西。期間還看了幾篇關於lambda演算的文章,理解了alpha,beta,eta變換和y組合子。由於學monad,又牽扯出了cps的問題,目前剛剛開始理解cont monad,還在跟callcc做鬥爭。從學haskell那天起,到現在已經5個月了。這特么什麼時候是個頭啊!
不是有句名言叫「Avoid success at all costs.」嗎
http://www.updike.org/articles/Pure_Lazy_FunctionalHaskell很乾凈漂亮,可tm的工程問題都很dirty啊…
簡單的說,對於well defined的問題,也就是有形式化描述的問題,都比較適合,比如編譯器,原型設計等。隨著問題dirty程度增加,使用難度越來越大。
打個比方,Haskell的魅力在於對編程範式的抽象,用它編程就像用各種形狀的積木搭房子,看起來很美,如果工具箱的積木都形狀合適的話。
問題就在這個「如果」上,對於有形式化描述的問題,工具箱的積木(抽象)足夠了,可大部分工程問題都沒有簡單的形式化表述的,這時候積木遠不如直接磚頭水泥這種簡單粗暴的方式來得方便。
再比如,其他答案提到的,有一類問題對正確性要求極高,會用到Haskell,這類問題經常都需要形式化的正確性保證,也就是說有個類似數學公式的東西,Haskell之類的函數語言非常適合。寫過一點haskell,感覺真的不適合生產環境。主要是我很難分析用到的內存和花費的時間。不過學習了haskell,對於編程能力的提高還是蠻大的,我知道了還有這樣的抽象方式。
複雜到一定程度的真實的項目都是99%取決於代碼實際運行的動態行為,而不是客戶代碼如何組織和表達。但是非真實的項目、個人項目,往往都追求靜態的代碼形狀是否「清爽」和「精鍊」,實際上那才起到1%的改進而已
誰說scheme用不上的,那不是emacs os的第一等語言嗎?
很負責任的說,Haskell沒有任何問題,Google一下"haskell at scb",五年前就已經上生產環境了而且頗受traders喜歡。
不適用
因為智商問題
拓寬思維 鍛煉邏輯
倒是不錯的考量haskell是複雜的問題搞得很簡單,簡單的問題搞得很複雜。無奈的是很多實際的問題不是那麼複雜,不需要那麼抽象。
讓我說啊,我覺得 Haskell 沒有實用性可言!
第一原因不是因為FP、不是因為Monad,而是因為工具鏈!
Haskell的cabal和stack難用到吐血!別跟我提hpack,想想就來火!簡直浪費我的時間!!!
用於生產環境,恐怕要求獲得國外CS的碩士學位、或國內CS博士學位、或國內CS學士+8年編程經驗的程序員。
適合用於文本處理等狀態少的環境吧
推薦閱讀: