Write Yourself a Scheme in 48 Hours/First Steps

原文舍败。
https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours/First_Steps

首先,你需要安裝一個(gè)ghc。在Linux上,它常常被預(yù)先安裝好了或者能夠通過apt-get或者yum命令來輕松搞定。你也可以從官網(wǎng)直接下載它食铐。不過除非你確信你想從源碼去編譯它,否則下載一個(gè)二進(jìn)制包就可以了僧鲁。像安裝其他的軟件包一樣下載和安裝它既可虐呻。這個(gè)教程是在Linux下完成的,但是只要你會使用相關(guān)的命令行操作寞秃,它在Windows或是Mac環(huán)境下也一樣能工作斟叼。

對UNIX或者Windows Emacs用戶來說,這里有一個(gè)很棒的Emacs mode春寿,包括了語法高亮和自動縮進(jìn)的功能朗涩。Windows用戶則能夠直接使用記事本或者其他文本編輯器:Haskell的語法對記事本相當(dāng)友好,盡管你仍要小心處理縮進(jìn)绑改。Eclipse用戶建議使用eclipsefp插件谢床。

現(xiàn)在,是時(shí)候?qū)懩愕牡谝粋€(gè)Haskell程序了厘线。這個(gè)程序?qū)⑼ㄟ^命令行讀入一個(gè)名字然后輸出一個(gè)問候語句识腿。建立一個(gè)以 ".hs” 結(jié)尾的文件并輸入下列代碼。當(dāng)心縮進(jìn)皆的,否則你的程序可能沒法通過編譯覆履。

module Main where  
import System.Environment  

main :: IO ()  
main = do 
      args <- getArgs  
      putStrLn ("Hello, " ++ args !! 0)  

我們來看下這段代碼。前兩行表示我們講創(chuàng)建一個(gè)名叫Main的模塊费薄,并且導(dǎo)入了System這個(gè)模塊硝全。所有的Haskell程序都會從Main模塊里的一個(gè)叫做main函數(shù)的地方開始運(yùn)行。你可以在這個(gè)模塊中導(dǎo)入其他的模塊楞抡,但是如果沒有了它伟众,編譯器就無法生成可執(zhí)行文件供用戶運(yùn)行。此外Haskell是大小寫的敏感的:模塊名稱需要是大寫開頭的召廷,而函數(shù)聲明則必須是非大寫開頭的凳厢。

main :: IO ()這行是函數(shù)的類型聲明:它表示main函數(shù)的類型是IO(),是一個(gè)返回Unit類型()的IO操作竞慢。一個(gè)Unit類型僅會包含一個(gè)值先紫,而(),它表示什么也沒有筹煮。類型聲明在Haskell里是可選的:編譯器能夠自動的識別它們遮精,當(dāng)你的聲明和編譯器自動識別發(fā)生沖突的時(shí)候它則會報(bào)錯(cuò)。在這個(gè)教程中败潦,為了更清晰的說明本冲,所有的類型都是顯式聲明的。而你在家里跟著做的時(shí)候劫扒,你可能更愿意選擇忽略檬洞,因?yàn)樵诰帉戇@個(gè)程序的時(shí)候其實(shí)并不太需要去在意它們。

IO類型是Monad類型類的一個(gè)實(shí)例沟饥,Monad是一種抽象的概念添怔,如果滿足以下這兩個(gè)條件,那我們就會說這樣的值是Monad:

  1. 這個(gè)值包含了一些特定類型的附加信息贤旷;
  2. 大多數(shù)函數(shù)不需要去關(guān)心這些附加的信息广料。

在這個(gè)例子里,

  1. 這個(gè)附加的信息就是將被執(zhí)行的IO操作遮晚;
  2. 而這個(gè)附加信息的值是不存在的性昭,表示成()

IO[String]IO()都同樣屬于IO Monad類型县遣,但它們有著不同的基本類型糜颠。它們作用于(或是傳遞)不同類型的值,[String]()萧求。

那些包含了附加信息的值則被稱作“Monadic”其兴。

Monadic值常被稱作“操作” ,因?yàn)樽钊菀椎乃伎糏O Monad用途的方法就是把它當(dāng)做一系列可能會影響外界世界的動作夸政。這一系列動作會傳遞一些基礎(chǔ)的數(shù)值元旬,然后在這個(gè)過程中每個(gè)動作都會對這些值進(jìn)行影響。

Haskell是一個(gè)函數(shù)式的語言:與給出計(jì)算機(jī)一系列指令從而讓它執(zhí)行不同,你需要給Haskell一系列定義來告訴它每一個(gè)函數(shù)來如何處理匀归。這些定義會將各種動作和函數(shù)組合在一起坑资。而編譯器會識別出將它們組織在一起的執(zhí)行方式。

要寫出這樣一個(gè)定義穆端,你首先需要建立一個(gè)等式袱贮。等式的左邊是一個(gè)名稱,可能還會帶有若干個(gè)與變量綁定的模式(后面會解釋)体啰。右邊的話攒巍,會給出一些由其他定義組合而成的式子,從而告訴計(jì)算機(jī)如何遇到該定義時(shí)如何進(jìn)行計(jì)算荒勇。這些等式就和一般的代數(shù)表達(dá)式一樣:你總是可以在程序中用等式右邊的部分來替代左邊的名字柒莉,并且得到與之前相同的結(jié)果。這種行為被稱作“引用透明”沽翔,而這種性質(zhì)使得Haskell代碼比其它的語言更加易于理解兢孝。

那我們應(yīng)該怎么定義我們的main函數(shù)呢?我們知道它必須是一個(gè)能夠從命令行讀入?yún)?shù)搀擂,然后從打印出一些輸出西潘,最終返回()(空值)的IO()操作。

這里有兩種方法創(chuàng)建一個(gè)IO操作:

  1. 使用return函數(shù)提升一個(gè)普通值進(jìn)入IO Monad哨颂。
  2. 連接兩個(gè)已經(jīng)存在的IO操作喷市。

因?yàn)槲覀兘酉聛硪鰞杉虑椋晕覀冞x擇第二種方法威恼。我們通過內(nèi)建函數(shù)getArgs讀入命令行參數(shù)并把它們存入一個(gè)字符串列表品姓。而內(nèi)建函數(shù)putStrLn則能夠讀入一個(gè)字符串然后將它輸出到終端。

我們使用一個(gè)do代碼塊來連接這兩個(gè)操作箫措。一個(gè)do代碼塊包括很多行腹备,所有的行按照第一個(gè)非空白字符在do后面排列,并且每行都可能是如下兩種形式之一:

  1. name <- action1
  2. action2

第一種形式將action1的結(jié)果和name綁定斤蔓,從而你可以在下一個(gè)操作中使用它植酥。例如,如果有action1的類型是IO[String](一個(gè)會返回一個(gè)字符串列表的IO操作弦牡,就和getArgs一樣)友驮,那name就會在接下來的一系列操作里和這個(gè)返回的字符串列表通過綁定操作符>>=綁定在一起。第二種情況僅僅執(zhí)行這個(gè)action2驾锰,并通過>>操作符同下一行連結(jié)在一起卸留。綁定操作符在處理不同Monad的情況下有不同的語義:在IO Monad中,它會連續(xù)執(zhí)行所有的操作椭豫,然后對外部世界產(chǎn)生這些操作帶來的副作用耻瑟。由于這個(gè)綁定符號的語義依賴你具體使用的Monad類型旨指,所以你并不能在同一個(gè)do代碼塊里把不同類型的Monad類型的操作糅雜在一起---在這里只有IO Monad是可用的(在同一個(gè)管道中)。

當(dāng)然喳整,這些操作可能自己會調(diào)用其他函數(shù)或是復(fù)雜的表達(dá)式谆构,然后繼續(xù)傳遞它們的計(jì)算結(jié)果(通過調(diào)用return或是其他最終調(diào)用了return的函數(shù))。

在這個(gè)例子里算柳,我們首先取出參數(shù)列表中的第一個(gè)元素(args !! 0)低淡,然后把它拼接到字符串"Hello,"的后面("Hello," ++)姓言,最后把結(jié)果傳給putStrLn瞬项。

就這樣,一個(gè)包含了之前所說的讀取和打印操作的新的操作就這樣創(chuàng)建完畢并存到了main這個(gè)返回值為IO()的標(biāo)識符中何荚。這樣Haskell系統(tǒng)就能夠識別并運(yùn)行它了囱淋。

Haskell中,字符串即是字符的列表形式餐塘,所以你可以對它使用任何的
列表函數(shù)或是操作符妥衣。以下是一個(gè)完整的標(biāo)準(zhǔn)操作符列表和它們對應(yīng)的優(yōu)先級:


懶得作圖就直接截圖的操作符一覽表

接下來編譯和運(yùn)行這個(gè)程序:

debian:/home/jdtang/haskell_tutorial/code# ghc -o hello_you --make listing2.hs
debian:/home/jdtang/haskell_tutorial/code# ./hello_you Jonathan
Hello, Jonathan

-o 選項(xiàng)指定了你想編譯出來的可執(zhí)行文件的路徑,然后你需要指定Haskell源代碼的路徑戒傻。

習(xí)題

  1. 修改程序税手,讓它能夠從命令行讀取兩個(gè)參數(shù)然后打印出一條包含它們的信息。
  2. 修改程序需纳,讓它能夠使用輸入的參數(shù)進(jìn)行簡單的四則運(yùn)算芦倒,建議使用read來講字符串轉(zhuǎn)化成數(shù)字類型,并用show來進(jìn)行相反的操作不翩。對各種不同的動作都操練一番兵扬。
  3. getLine是一個(gè)從命令行讀取一行輸入信息然后返回字符串的IO操作。修改程序口蝠,讓它能夠提示需要一個(gè)名字并讀取這個(gè)名字而不是像之前那樣直接從命令行傳入?yún)?shù)器钟,最后打印它。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妙蔗,一起剝皮案震驚了整個(gè)濱河市傲霸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌眉反,老刑警劉巖昙啄,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異禁漓,居然都是意外死亡跟衅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門播歼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伶跷,“玉大人掰读,你說我怎么就攤上這事“饶” “怎么了蹈集?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長雇初。 經(jīng)常有香客問我拢肆,道長,這世上最難降的妖魔是什么靖诗? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任郭怪,我火速辦了婚禮,結(jié)果婚禮上刊橘,老公的妹妹穿的比我還像新娘鄙才。我一直安慰自己,他們只是感情好促绵,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布攒庵。 她就那樣靜靜地躺著,像睡著了一般败晴。 火紅的嫁衣襯著肌膚如雪浓冒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天尖坤,我揣著相機(jī)與錄音稳懒,去河邊找鬼。 笑死糖驴,一個(gè)胖子當(dāng)著我的面吹牛僚祷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贮缕,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼辙谜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了感昼?” 一聲冷哼從身側(cè)響起装哆,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎定嗓,沒想到半個(gè)月后蜕琴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宵溅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年凌简,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恃逻。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡雏搂,死狀恐怖藕施,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凸郑,我是刑警寧澤裳食,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站芙沥,受9級特大地震影響诲祸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜而昨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一救氯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧配紫,春花似錦径密、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽底桂。三九已至植袍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間籽懦,已是汗流浹背于个。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留暮顺,地道東北人厅篓。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像捶码,于是被迫代替她去往敵國和親羽氮。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容