學過Haskell是一種怎樣的體驗?


發現跟沒學過Haskell討論問題的時候,思想上有巨大的隔閡。


1. 覺得沒學會

2. 強迫症更嚴重了


呃,之前誰騙我說haskell很難的......


上機課上,總手抽得想寫haskell ,同時抱怨 xx 語言 沒有 xx ,然後就在各種大作業下 附上了 haskell 的代碼


This is what happens to ones Javascript after having learnt Haskell (x-post from /r/node) : haskell

這是在 Reddit 的 Haskell 板上的一個帖子,摘抄部分代碼:

#!/usr/bin/env node

var
exec = require("child_process").exec
, Maybe = require("data.maybe")
;

const HOG_DEFAULT = "mem";
const QUOTA = 25;

// data Hog = { name :: String, mem :: Number, cpu :: Number }

// Generic Helpers

// head :: [a] -&> Maybe a
var head = function(l) {
return l.length ?
Maybe.Just(l[0]) :
Maybe.Nothing();
}

// element :: [a] -&> Number -&> Maybe a
var element = function(l, i) {
return l.length &> i ?
Maybe.Just(l[i]) :
Maybe.Nothing();
}

// tail :: [a] -&> Maybe [a]
var tail = function(l) {
return l.length ?
Maybe.Just(l.splice(1, l.length)) :
Maybe.Nothing();
}

// last :: [a] -&> Maybe a
var last = function(l) {
return l.length ?
Maybe.Just(l[l.length - 1]) :
Maybe.Nothing();
}

// contains :: [a] -&> a -&> Boolean
var contains = function(l, el) {
return l.indexOf(el) != -1;
}

// containsAny :: [a] -&> [a] -&> Boolean
var containsAny = function(l, els) {
return l.reduce(function(p, c) { return contains(els, c) || p; });
}

// defaultMaybe :: Maybe a -&> a -&> a
var defaultMaybe = function(maybe, d) {
return maybe.cata({ Just: function(x) { return x; },
Nothing: function() { return d; }});
}

// Program Helpers

// printUsage :: IO ()
var printUsage = function() {
console.log("usage: hog [-h|--help] &
"
+ " where: -h|--help = please help me
"
+ " cpu = show cpu hogs
"
+ " mem = show memory hogs
"
+ " default = mem"
);
}

// internalError :: IO ()
var internalError = function(err) {
console.log("Internal error: " + err);
process.exit(1);
}

更多參考:https://github.com/hellerve/hog/blob/master/index.js


兩個真事:

01 一個朋友有次看到 &<= 半天沒反應過來這是什麼

02 在racket repl那裡至少兩次打了 :t


寫haskell的時候,成天抱怨currying不好理解,monad不好理解。。。換了工作之後讓我去寫java,每寫一個for循環我都覺得自己委屈得想砸鍵盤。


沒啥特別的感覺,我學過好多次了,就是每次都學不會。。。。。。

不得不說,Learn you a haskell 的插圖做的實在是好。為了這些萌蠢的圖,我要把教程看完。。。。

看到好多人說,學了haskell會打開新世界的大門。所以我開始了我的旅程。。。。

前兩章,似乎也沒有什麼很難的嘛!

函數符號啥的似乎也沒啥,挺容易懂的啊,hoho!

然後,到了高階函數。。。。

哎,這個以前沒有見過啊!我要多看看。

然而也並沒有那麼難,順利理解!

模組也好說。

不過類型系統好像有點麻煩。。。

這個遞歸式數據結構又是怎麼回事。。。

理解完這些之後,我以為我已經入門了

哈哈,我要用haskell征服世界!

然而並沒有。。。。。。

好像後面的內容才是本體啊。。。。

我慢慢啃去了。。。

總的來說,學haskell的感受在如下兩圖中隨機切換:

咦,原來是醬紫!

什麼鬼,我的大腦需要先去散熱下!最後附上 Learn you a Haskell 網址

Learn You a Haskell for Great Good!


學過Haskell有以下後遺症:

1. 習慣每個函數不超過十行。

2. Pattern Matching重度依賴症。

3. 從不寫循環,統統各種fold和尾遞歸。

4. 習慣curring和compose,喜歡point free。

5. 寫代碼時基本不考慮性能,相信Haskell的惰性求值和GHC的優化能力。

6. 喜歡$和!。

7. 看大多數編程語言都不順眼:)

8. 理解其他「新」語言概念毫無壓力(比如Rust)。

9. 可以用Monad抑或Category Theory裝13。:)


寫 python 的時候,會在注釋或者 doc 中,給每個函數添加類型簽名。


1. 純函數:能夠讓整個程序變得可推理,有條理,代碼直接精確反映了我們的(邏輯)推理。

2.精確代碼:立即寫代碼,馬上就能重構,更少的代碼讓你重構更容易。

3.健壯代碼:靜態語言 類型推斷和智能的編譯器。

4.測試:類型系統大大降低了大型類的單元測試,快速檢查是另外一類測試風格,能通過自動生成你的函數的斷言測試用例;當然手動測試還是最重要,包括IO相關故障。

5. IO高並發:GHC的線程抽象和IO管理器,易於從並發執行計算角度考慮,並能得到基於事件的非同步運行框架如Node.js的所有優點。其次,GHC有一個類似Node.js的非堵塞IO,支持實時多線程和自然地多核(Node.js需要cluster庫包支持多核),可以像Node那樣使用事件編程,這真的不是一場公平競爭。

6.豐富庫包:Haskell庫包非常易於集成。

7.部署:私有雲部署Haskell非常容易,因為所有依賴的庫包都是靜態鏈接,能夠一步到位進行版本控制和部署。


還好,思維上打開了一扇通往新世界的大門,但也僅限於此了。

目前只是覺得在做Parser的時候很好用,其餘時候也就一般。

代碼是很簡潔,但是思維上需要多走一些路,然後比較複雜的函數或者nested function在理解(自己看自己的,或者看別人的)或者debug的時候會比較蛋疼。

基本上遇到常規問題根本不會想起它。


每次寫完代碼,總想搞的更精簡,再精簡


寫code的時候會一直想

怎麼縮成一行

怎麼縮成一行

怎麼縮成一行

。。。

重要的事情說三遍也不一定有效果啊!

摔(╯°□°)╯︵ ┻━┻


現在能把所有語言寫成函數式編程


回到我Py,

lst = [1]
head, rest = lst.append(lst)

竟然沒覺得不對。。。


開眼界了,類型系統吊暴了有木有,怎麼沒早點學呢


再寫Python明明可以用列表解析的我也要寫map/filter + lambda......

還有...重新賦值變數的時候會很緊張...想重命名一個...


搞過vert.x之後再看haskell,難度下降了至少一半,如果不是一大半的話

很多概念都見過,比如immutable,java至少在當下,是沒有immutable類型的

除了string和primitive type,value type還在做

但是vert.x中,verticle之間會強調使用immutable對象

所以immutable這個東西會在接觸haskell之前就了解,這是一個

另外一個,pure function,這個倒是跟vert.x無關,但是vert.x的原理會解釋它是如何處理並發的

文檔只要走一波就一定需要理解這個東西,否則體會不到vert.x的好

而vert.x跟spring等的主要區別點,就在這個pure function上,spring反而強調pure function

真是個笑話,vert.x不強調這一點,從這一點上說,vert.x自由度更大

但是要搞懂這個自由度,就需要理解pure function的機制,在並發環境下的好處

所以這是另外一個,在學習haskell之前就會搞懂的東西

第三個,非常重要的,monad的實現,在vert.x中就有future予以實現

而且這個是pure java的實現,解決的僅僅是一個callback hell的問題

但是不管怎樣,都會接觸一下,就沖能解決callback hell,也會了解future是腫么一回事

所以等到haskell用的時候,就太high了,這特么見過啊,一下子就理解了

而如果一開始就強上monad,就覺得無法理解,因為很多人解釋不清楚這個好處在哪裡

等callback hell這個搞定之後,你再回頭去結合pure function,去理解副作用之類的

那就更自然而然了,vert.x中經常會有人討論execute blocking造成的並發問題

這個用pure function一解釋,清晰自然

而且一般走到這一步,都會幾個語言了,java, groovy和kotlin,多半是這三個

那概念有些是java沒有的,但是kotlin有啊,而且coroutine之類的,kotlin還更多

這個時候我們學習時候就可以對比批判地看這些pure fp的好壞了

可能有些人還是覺得scala好,這很正常,但是我開始逐步傾向於pure的做法

就是將來可能會選擇groovy+java+haskell的方式開發,這樣可以從文件後綴上直接看出來差異

不會造成思想上的混亂,當然groovy有java的oop的寫法,那就不用就是了

等這些東西都理解了,haskell大部分就剩下語法了

打開視野,多個語言,polyglot太有趣了,以前覺得vert.x可能最大的作用在於什麼並發的規避

多個網路協議的介面,blablabla,但是越到後面越覺得,vert.x的polyglot太重要了

因為這就是打開一扇又一扇新世界的大門的鑰匙,只有通過對比,你才能更加深刻地領悟到

為什麼我們要用pure fp,而當別人提出疑問的時候,你才能回答上來

嗯,將來估計會有一波haskell vs scala的大混戰,趕緊把這個平台搭建好

為這一波史詩對決做準備


正在學的路上,看的也是大家推薦的趣學指南。其實最大的感受就是會不自覺的和cpp和java作比較,然後亂想一些自以為是更本質的一些東西(當然可能我只是自己在YY)。公司里有一個寫了八年的Haskell的架構師跟我說,這東西很難,但是沒有那麼難,還是要堅持一下。嗯,雖然是初學者,但是很明顯能感受到思考問題上的一些轉變的。這種感覺其實很爽,興許你就會發現自己其實是個語言愛好者而摒棄那種從一而終的想法。



「啊 DFA?把狀態也當參數傳進去做 pattern matching 然後外麵包個殼就好啦。」


推薦閱讀:

PureScript 是什麼?有什麼特性
精通 Haskell 是一種怎樣的體驗?
Haskell等語言中的模式匹配在C++中如何實現?
編程語言中的「組合性」是什麼意思?
柯里化對函數式編程有何意義?

TAG:Haskell | X是種怎樣的體驗 |