阻擋你學會 Haskell 最大的兩個問題是什麼?
作為一門被許多大神推崇, 同時有著清晰的教程的一門速度飛快的語言
很多人應該都嘗試去學過的, 但真的, 這麼難學的一門語言不像 JS 那樣大街上都是學會了 Haskell 的大俠就... 學會了就不會覺得那麼難, 說起來會不一樣的吧如果你沒學會或者沒學會或者沒登堂入室, 最大的難點是哪些?
1,Haskell的相關書籍比較匱乏,數量上我用手指就能數得過來。書且各有側重,寫Haskell相關的書想系統地結合好理論與實踐非常困難!不信你可以寫一本試試。
Programming in Haskell
Learn you a Haskell for great good
The craft of functional programming
Introduction to Functional Programming Using Haskell
School of Expression
Real World Haskell
Beginning Haskell
Haskell for data analysis
Parallel and Concurrent Programming in Haskell
Developing web applications with Haskell and Yesod
其中前4本是教學用的,根本無法指導工程實踐。理論跟實踐比較好的就是School of Expression,但是很多不是常用的庫,很多方向如FRP、Memoization沒有深入地介紹。RWH是一本非常好的書,但是很多庫已經太舊了,不能使用了,但是書還是可以看,在線版的有討論,書中不翔實的地方都有人給出解釋,十分不錯。Beginning Haskell實踐部分很不錯,但是理論部分幾乎沒有。Haskell for data analysis沒看過,不發表評論。Parallel and Concurrent Programming in Haskell只是講並行與並發的,但是一本難得的Haskell好書。高級的Haskell相關的書,最好的一本就是Michael Snoyman的DWAHY了,工程上是一本非常好的書,但是你需要了解一些如何使用TH與QQ,還有一些其他相關的內容,但是遺憾的是沒有講這些內容。Haskell每本都如珍珠一般,這些書的作者也者是相當強悍的人,Paul Hudak、Graham Hutton,Simon Marlow等等。但是C++、Java、JS的書我能隨便就搜出上百本,無論中文還是英文。
2, Haskell學習曲線本身非常陡峭。
程序員本身的思維定勢是一個嚴重的問題,以為語言都長得跟C差不多。更有甚者覺得Haskell不是圖靈完備,理由是Haskell不能賦值。
類型檢查與類型推斷是第一個坎,上邊的書沒有一本講類型推斷大約是怎麼樣的,所以我開始的時候無法理解flip id,liftA3 id這樣的函數,我是讀研的時候學了Lambda演算與類型這門課里的simple typed lambda calculus還有PCF,看了Hindley的那本Lambda-calculus and Combinator才完全理解的。類型系統後邊還有Kind,KindPolymorphism以及將會出現的Kind coercion。
Monad,Monad Transformation,Monad Control是第二個坎,Monad這東西剛開始學的時候很奇怪,很抽象,像是順序式編程,但是又不是,列表與Lazy IO就不是,它是一種設計模式,抽象順序式地計算不過只是它的一部分而已。你以為看會了Monad就完了,其實遠遠沒有,Michael那本書里還有相當多的內容。
後面的Arrow的設計方法就要比Monad更加抽象了,後邊還有Arrow Transformer。參考文獻只有論文了,根本沒有書,都是十幾頁的,但是想自如地用起來可能還要繼續Hack很久。此外還有一些庫用到了Category theory,給了極高的抽象能力,這裡Arrow本身就是Category類型類上面的抽象。
以上內容,絕對夠你讀個一年的研究生。
3 GHC進化相當之快
Haskell已經引入了Type family,PolyKind,DataKind這些擴展,能完成部分Dependent type的功能。為了補過去bug,還引入了type role,safe coercion,這後面每一個課題都有一個或者幾個博士與之對應,比如PolyKind,DataKind對應荷蘭Utrecht大學的Jose Pedro Magalhaes也就是UHC的誕生地,Dependent type對應了Chalmers大學的Ulf Norell以及Strathclyde的Adam Gundry,之後又有一系列的東西比如Dependently Typed Programming with Singletons邊邊角角的內容。
GHC每年都要發布幾個版本,7.9已經完成了(但沒release你要自己編譯),7.10的RC已經放出,7.12已經在孕育當中了,時常要加入大量的擴展。很多特性的加入是一環扣一環的,並且沒有文檔較好地總結他們,很多論文已經很陳舊了,SPJ那篇Template Haskell的論文很多代碼不能直接用了,Why it is nice to be Quoted中很多的語法也已經被改了,給學習帶來了一些不必要的麻煩。學習了這麼久才發現只能剛剛跟上GHC的腳步,他們討論的東西我才能懂一些。
4 庫的混沌
很多Hackage上的庫注釋都不怎麼有,尤其是在看Yampa的時候,好多switch沒有注釋,給wiki鏈接只有個圖,沒解釋!FRP的變體也很多,沒有論文敘述了這些idea的發展,給學習造成了一定的困難。另外還有一些庫死掉了,Haskell wiki連過去的鏈接也一起跪了,需要上wayback machine才能找到。Haskell庫的學習一般不外乎看論文,看wiki或者看某些人的博客,不過現在這些情況有所改觀,畢竟有幾家Haskell公司成立了,conduit以及基於他們的庫也相當成熟了,配合論文再看代碼還可以接受。
5 環境因素
中國開函數式編程課的大學屈指可數,中山大學的喬海燕老師的函數程序設計在他那裡是公選課,就是跟太極拳、養魚這種課一起的! 之前看他們一個本科生畢業設計用Haskell做的QuickCheck檢查的論文後實感無力,這麼淺顯的東西是不能做畢業設計的,但物以稀為貴,有人做就是要鼓勵的。所以這類語言使用的人口基數上我們就差了一大塊,中文的參考文獻跟英文比起來幾乎相當於沒有,所以發展得不好,使用的人少,遇到問題沒有人問,給學習也帶來了困難。
我很好奇為什麼是兩個問題。。
是這樣,拋開本身語言學習角度的門檻不說,這門語言習得的另一個門檻是實踐。
我們學習一門語言,不是為了裝逼,是為了實用。當然,你可以說學習一門函數式語言可以讓我們領略另一種風格,你可以去看看《Learn you a Haskell for great good》去感受,但是領略過後帶來的就是忘記,以及類似於女孩子頭髮拂過臉龐的一些taste般的還念。 真的想要用一門語言,沒有一段時間工程實踐所形成的肌肉記憶,是行不通的。
學習 Haskell,你會滿足於刷過Haskell 99 problem 和 hackerrank上的題目嗎, 那樣其實沒有實感,對吧?
於是我們可以拿haskell幹什麼呢?拋去前人的奇技淫巧(比如xmonad, 比如FB中的一些開源項目),我能想到的東西就是解釋器。對,其實函數式語言的風格非常適合寫解釋器,於是開始嘗試用Haskell來實現一個類scheme風格的東西,於是開始擼token, parser, 但是把基本的東西完成後,你發現你還是不滿足。
於是你開始加入各種state-of-the-art特性和語法糖。 加call-by-need/value, 加first-class function, 加GC, 加type inference。
於是你發現你想學的東西越來越多,你發現你對函數式語言的執行效率不太滿意,你發現你可能需要了解更多的理論知識。你扔掉Real World Haskell, 開始看okasaki的pure functional data structure, 開始看The.Implementation.of.Functional.Programming.Languages, 學習lambda calculus, 搞起了type checker, graph reduction, G-Machine...
你還記得你想要幹什麼嗎?
我只想學學Haskell而已。
Haskell不僅僅是Haskell,且不說monad, point-free之流, 學Haskell不僅僅意味著學習Haskell本身,還要學習很多其他的東西。實際上即便是你不搞編譯器解釋器,你浸淫FP愈久,這些東西都是不可避免的。而這些內容無論哪個都非常tough, 無形中提升了haskell的自學門檻。
還有一些人路被帶歪陷入範疇論的深坑不能自拔。
那麼哪裡能得到更好,可有先賢指導的haskell實踐機會呢? 我知道FB是招haskell工程師的, GSoC每年也會有一些haskell的開源項目,比如GHC擴展之類的。但是位置就這麼多,僧多粥少,於是國內除了top0的大神和其他學校的一些大神外,大家都只能靠自學苦苦熬著。然後你就迷茫了,
我學的到底是什麼呢?
===================================================================
但是以上其實都是借口罷了,能掌握的人總是能通過各種方法掌握,庸才如我則會給自己找各種各樣的理由。
比如我認識的S君,一個學期就基本上能用Haskell做一個完整的final project, 而JS的C君學習OCaml(another functional programming language)僅僅2周就寫出了一個比較成熟的toy language(帶各種小功能,比如並行編譯之類的
說穿了,不過是嘗試將新的思維體系融入已有的思維體系中罷了,有的人很快就把思維轉換了過來,有的人(比如我)就始終無法跳過龍門。
說到底都是智商的錯=。=,說白了就是太菜。卒。就說一個:最大的問題就是沒去Facebook寫Haskell:https://www.haskell.org/wikiupload/c/cf/The_Haxl_Project_at_Facebook.pdf
你不會抽象代數別想學會 haskell
我記得我剛開始學時,最大的兩個問題
1. 總是在和以前學過的知識,做不恰當的類比。學過c/c++,學Haskell的時候,就總是在想,這個xx特性是不是等價於c/c++中的那個特性!腦子總在想:為什麼說沒有賦值,為什麼說「值」都是函數,這個「=」是賦值了吧!!這個「&<-」是賦值了吧。。。。。2. 在沒學會走的時候,總想先學會跑。RWH一翻,我艹,前幾章太簡單了,什麼亂七八糟概念我不要看,不要聽,我都會c/c++了看毛看,我要寫實際的程序!!直接翻後面嘛。。。傻眼。不會python、perl、R這種,看代碼還能大致看明白在做啥,Haskell,不太可能。。。解法:踏踏實實,心態擺正,做個無知的初學者,哪怕一開始很多東西看起來很蠢。比如 id :: a -&> a, Maybe之類2015年4月27日更新:
Haskell的關鍵是兩點,一是需要徹底丟棄命令式的編程思維習慣,要習慣用函數式的思維來解決問題。二是要根據自身的情況把握好理論和實踐的界限,Haskell是理論和試驗性很強的一門語言,有很多理論上的新東西都會拿到Haskell上來試驗一番。因此要會分辨哪些是給搞理論的人玩的,哪些是工程實踐需要的。
至於範疇論,還是看一些基礎入門的東西吧,要不然有些實用的庫看起來很累的。----- 我是分割線 --------
感覺自己應該是學會Haskell了,現在的障礙是缺少有一定複雜度和規模的程序來實戰。到現在也只是用Haskell寫了一些工具、做了一些題目而已。學習Haskell最具里程碑的一道坎是很多人提到的Monad,Monad確實是Haskell中一個很基礎的概念。掌握Monad後其他後續的Free Monad等就好理解了。利用好Monad和Applicative這兩種Class就可以寫出和命令式語言相比簡約很多的代碼了。掌握State、((-&>) r)、Maybe、List、Cont等常用的數據類型就可以寫出不少好代碼了。另外再學習好parsec,很多parse類的事情就簡單了。對我來說最大的問題是:
我不知道應該用來幹什麼還是有句話說的好:「Haskell最大的用途就是影響其他語言」工作和生活中用不到是最大障礙,也是我阻止我學習其他知識的最大障礙。
bhuztez和erlang.
我覺得自己差不多算「登堂入室」了Haskell。 個人感覺阻礙學習的一大問題是道聽途說,江湖上跟Haskell相關的不實傳言泛濫,誤導小白。誰TM說學Haskell就需要學範疇論的?想我連一門函數式語言都不會的時候,就去興沖沖地翻那本Steve Awodey的藍皮書,想學範疇論。。。草稿紙上畫了好多箭頭,最後未果,鬱悶了好久。。。當然,深入學習Haskell跟範疇論脫不開關係,可是入門真的用不著啊,哪怕學到monad也用不著啊。。。
初學者學Haskell還是得動手為主,一些概念形成了肌肉記憶以後再來看教材/論文才會感覺make sense。。。當然,不排除你是畫態射圖如嗑瓜子般輕鬆的學霸,那當我啥都沒說。我發現回答的都是學會了的
一個是邵巨巨說的範疇論。。。還有一個是我被 Lisp 慣壞了。。。現在沒有 SLIME 都不會寫代碼了。。。
目標不明確,在入門階段要學習各種語法,這個有明確目標很容易就上手了。但是後面那些高端的內容就出現很多看不明白為什麼要這樣了,比如monad。我也知道了基本語法,但是沒有人說明白為什麼一定要用monad(非io這種副作用時),所以也到現在也只是略知
缺少應用,很少又相關應用,實戰的機會少居然沒有人提到Monad
智商和實踐機會。
缺少具體的應用場景,對於初學者而言,學scala至少能用java來進行一些彌補,所以我能在沒有學過scala的情況下去修改比如ss-android的代碼,而Haskell沒辦法我就只能去codewars上面靠刷題來提升了。