Haskell學習筆記(一)

這一系列的筆記主要參考中文版的 Real World Haskell,這篇博文作為本系列的第一篇浙垫,先介紹一下Haskell的語法和一些基本知識刨仑。


進入/退出交互模式ghci

安裝好Haskell夹姥,命令行敲ghci進入交互模式

Prelude> :set prompt “ghci>”
ghci>:q                       -- 退出

基本算術

ghci> 1 + 1
2

ghci> (+) 1 1
2

ghci> 2 + (-1)     -- 負數是通過唯一的一元操作符'-'得到,-1的括號不能省略
1

ghci> True && False
False

ghci> True || False
True

ghci> :info (+)      -- 操作符的信息可以通過':info'方式查看
class Num a where
  (+) :: a -> a -> a
  ...
    -- Defined in ‘GHC.Num’
infixl 6 +           -- infixl代表加法是左結合的辙售,優(yōu)先級為6

ghci> :info (^)
(^) :: (Num a, Integral b) => a -> b -> a   -- Defined in ‘GHC.Real’
infixr 8 ^        -- 乘方是右結合的轻抱,指數b的類型是Integer,優(yōu)先級為8

ghci> not True    -- not是一個內置函數旦部,不可以通過:info查看其信息
False

ghci> 1 == 1
True

ghci> 1 /= 1
False

ghci> let e = exp 1     -- 添加綁定
ghci> e ^ 1
2.718281828459045
ghci> e ** pi      -- 指數不是整數時较店,需要更換操作符
23.140692632779263

列表和元組

列表表示一系列相同類型的元素集合容燕,元組則可以包括不同類型的元素梁呈,void在Haskell中被實現為一個空的元組

ghci> [1,2]    -- 列表
[1,2]

ghci> [1..5]
[1,2,3,4,5]

ghci> [1,3..9]
[1,3,5,7,9]

ghci> [1] ++ [2,3]  -- 列表的連接
[1,2,3]

ghci> 1 : [2,3]  -- 元素和列表的連接缰趋,類似cons
[1,2,3]

ghci> head [1,2,3]   -- 返回列表的第一個元素
1

ghci> tail [1,2,3]   -- 返回除去第一個元素后的剩余列表
[2,3]

ghci> last [1,2,3]   -- 返回列表的最后一個元素
[3]

ghci> init [1,2,3]   -- 返回除去最后一個元素的剩余列表
[1,2]

ghci> reverse [1,2,3]
[3,2,1]

ghci> take 2 [1,2,3]  -- 返回列表的前n個元素組成的新列表
[1,2]

ghci> drop 1 [1,2,3]  -- 返回丟棄前n個元素后得到的新列表
[2,3]

ghci> null []
True

ghci> (1, "Hello")    -- 元組
(1, "Hello")

ghci> fst (1,"Hello")  -- 取元組的第一個元素
1

ghci> snd (1,"Hello")  -- 取元組的第二個元素
"Hello" 

字符串

Haskell的字符串和C的非常相似秘血,用單引號表示單個字符味抖,雙引號代表字符串灰粮,字符串實際就是單個字符的列表,但不需要像C中用'\0'結尾

ghci> 'a'
'a'

ghci> "Hello World"
"Hello World"

ghci> ['H','e','l','l','o']
"Hello"

ghci> "" == []
True

ghci> 'a' : "bc"
"abc"

ghci> "a" ++ "bc"
"abc"

查看表達式類型

在交互式界面下熔脂,我們有兩種方法查看表達式的類型:

ghci> :set +t
ghci > 'a'
'a'
it :: Char    -- it是交互模式下存儲運算結果的變量
ghci> :unset +t
ghci> 'a'
'a'

ghci> :type 'a'
'a' :: Char
ghci> :type 1 + 1
1 + 1 :: Num a => a    -- :type執(zhí)行靜態(tài)的類型推導柑肴,并不會顯示運算結果2的類型

分數

ghci> :m +Data.Ratio      -- ':m'代表載入模塊
ghci> :set +t
ghci> 1 % 2               -- 分數1/2
1 % 2
it :: Integral a => Ratio a

整數范圍

Haskell中的整數是不限大小的,你可以寫出下面的式子:

ghci> 313 ^ 15
27112218957718876716220410905036741257

自定義函數

在ghci中定義函數的語法和標準Haskell有所不同晰骑,我們在后者環(huán)境下定一個函數add,并加載到ghci環(huán)境中:

-- this is in myDrop.hs
myDrop n xs = if n <= 0 || null xs
              then xs
              else myDrop (n - 1) (tail xs)
-- back to ghci mode
ghci> :load myDrop.hs
ghci> myDrop 2 "cat"
"t"

副作用

避免函數的副作用有很多好處秽荞,在Haskell中抚官,定義的函數默認都是無副作用的(純函數),有副作用的函數在Haskell中類型會帶有IO標簽:

ghci> :type readFile
readFile :: FilePath -> IO String

純度減輕了理解一個函數所需的工作量凌节。一個純函數的行為并不取決于全局變量、數據庫的內容或者網絡連接狀態(tài)彪见。純代碼(pure code)從一開始就是模塊化的:每個函數都是自包容的娱挨,并且都帶有定義良好的接口捕犬。
將純函數作為默認的另一個不太明顯的好處是酵镜,它使得與不純代碼之間的交互變得簡單柴钻。一種常見的 Haskell 風格就是淮韭,將帶有副作用的代碼和不帶副作用的代碼分開處理。在這種情況下靠粪,不純函數需要盡可能地簡單毫蚓,而復雜的任務則交給純函數去做。
軟件的大部分風險元潘,都來自于與外部世界進行交互:它需要程序去應付錯誤的、不完整的數據翩概,并且處理惡意的攻擊,諸如此類牍鞠。Haskell 的類型系統(tǒng)明確地告訴我們评姨,哪一部分的代碼帶有副作用,讓我們可以對這部分代碼添加適當的保護措施参咙。
通過這種將不純函數隔離、并盡可能簡單化的編程風格择同,程序的漏洞將變得非常少净宵。

變量

在Haskell中,一個變量和一個值建立綁定之后择葡,這個變量的值就不可以再被修改了,舉個例子阻星,下面的代碼是無法通過編譯的:

-- file: ch02/Assign.hs
x = 10
x = 11

命令式語言中的變量是和一個內存地址建立了綁定,但地址里寫的內容是可以反復修改的妥箕,所以在命令式語言中不同時刻讀取同一變量的值可能會得到不同的結果。在Haskell中坎吻,變量是和值建立的綁定宇葱,一個變量被綁定后,我們總能把變量替換成綁定的值黍瞧。

惰性求值

Haskell中用于追蹤未求值表達式的記錄被稱為塊。編譯器通過創(chuàng)建塊來延遲表達式的求值弦讽,直到這個表達式的值真正被需要為止膀哲。如果某個表達式的值不被需要,那么從始至終某宪,這個表達式都不會被求值。在Haskell中可以定義無限長的數組蔼囊,并可以對其進行一些操作:

-- mycons.hs
mycons n = n : mycons (n + 1)
l = mycons 0       -- l是自然數集合

-- ghci
ghci> :load mycons.hs
ghci> take 3 l
[0,1,2]
ghci> (!!) l 0    -- !!是根據下標取列表元素的操作衣迷,從0開始
0
ghci> takeWhile(\x->x<3) l
[0,1,2]

Haskell還自帶了一個repeat::a->[a]函數,他接受一個參數x壶谒,返回一個無限個x組成的列表。

類型系統(tǒng)

Haskell的類型系統(tǒng)基于簡潔而強大的 System F让禀,這里我們不深究其實現陨界,只列出Haskell類型系統(tǒng)的三個特性:

  • 強類型:強類型語言不會做隱式的類型轉換。舉個例子菌瘪,如果將一個整數值作為參數傳給了一個接受浮點數的函數,C 編譯器會自動且靜默(silently)地將參數從整數類型轉換為浮點類型缀皱,而 Haskell 編譯器則會引發(fā)一個編譯錯誤。
  • 靜態(tài)類型:靜態(tài)類型的語言會在編譯階段求出所有變量和表達式的類型啤斗,并拒絕執(zhí)行任何類型錯誤的程序赁咙。同時,Haskell還提供了 typeclass 機制讓程序員實現一些動態(tài)類型語言的功能崔拥。
  • 自動推導:如果沒有自動推導凤覆,那么一門靜態(tài)語言就要求程序員事無巨細地顯示聲明所有變量的類型以及類型之間的關系,就像Java采用的norminal type system盯桦。和很多函數式語言一樣,Haskell可以幾乎自動推導出所有表達式的類型(有時需要程序員提供一些必要的提示)贴膘。這使得程序員在編碼時幾乎不需要寫任何的類型信息(寫出來當然也是可以的)略号,但同時編譯時期也有強大的類型檢查保證Haskell代碼的類型安全。

多態(tài)

Haskell中列表中的值可以是任意類型玄柠,所以我們可以稱列表為類型多態(tài)(polymorphic)的。任何列表相關的操作函數應當也是多態(tài)的宫患,看一個例子:

ghci> :type last
ghci> last :: [a] -> a

這里last的類型中包含了一個類型變量a铐伴,在不同情況下它會具化成不同的類型,當last函數應用于一個字符串的時候当宴,其類型就是[Char]->Char,而應用于一個整數數組時玲献,last的類型就是[Integer]->Integer

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末瓢娜,一起剝皮案震驚了整個濱河市礼预,隨后出現的幾起案子眠砾,更是在濱河造成了極大的恐慌托酸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谷丸,死亡現場離奇詭異应结,居然都是意外死亡,警方通過查閱死者的電腦和手機揩慕,發(fā)現死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門砾层,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人止吐,你說我怎么就攤上這事侨糟“樱” “怎么了秕重?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵溶耘,是天一觀的道長。 經常有香客問我凳兵,道長,這世上最難降的妖魔是什么饭望? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮厌漂,結果婚禮上,老公的妹妹穿的比我還像新娘苇倡。我一直安慰自己囤踩,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辞州,像睡著了一般。 火紅的嫁衣襯著肌膚如雪埃元。 梳的紋絲不亂的頭發(fā)上媚狰,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音类嗤,去河邊找鬼。 笑死遗锣,一個胖子當著我的面吹牛嗤形,可吹牛的內容都是我干的。 我是一名探鬼主播赋兵,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼霹期,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了经伙?” 一聲冷哼從身側響起勿锅,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤枣氧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后张弛,有當地人在樹林里發(fā)現了一具尸體酪劫,經...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年刻剥,在試婚紗的時候發(fā)現自己被綠了滩字。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡漓藕,死狀恐怖挟裂,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情诀蓉,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布划滋,位于F島的核電站埃篓,受9級特大地震影響,放射性物質發(fā)生泄漏架专。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一想邦、第九天 我趴在偏房一處隱蔽的房頂上張望委刘。 院中可真熱鬧鹰椒,春花似錦、人聲如沸漆际。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽擂找。三九已至,卻和暖如春贯涎,著一層夾襖步出監(jiān)牢的瞬間慢洋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留礁遣,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓杏头,卻偏偏與公主長得像沸呐,于是被迫代替她去往敵國和親醇王。 傳聞我的和親對象是個殘疾皇子崭添,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內容