到目前為止,我們一直在GHCi下試驗Haskell代碼。這的確很方便,而且可以馬上看到結果。不過,有時候也有不方便的地方。比如,有時我們需要用到以前定義的函數,那就必須重新把這定義輸入一遍(GHCi不會記住以前的會話中的內容)。以後,隨著Haskell代碼的變長以及復雜化,所有代碼都在GHCi下輸入,會非常不方便。那麽,我們可不可把Haskell代碼保存在一個文件中呢?
當然可以。用你慣用的文本編輯器新建一個新文本文件,輸入以下內容:
areaCircle r = pi * r^2
注意:縮進在Haskell中是有意義的。小心有不必要的縮進出現。保存為Varfun.hs(hs為Haskell的縮寫)。
然後在GHCi下用load命令(:load或:l)載入文件:
Prelude> :load Varfun.hs
Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>
如果GHCi提示錯誤“Could not find module 'Varfun.hs'”,那可能是Varfun.hs文件不在當前目錄下。你可以使用:cd命令進入Varfun.hs所在的文件:
Prelude> :cd /home/weakish/haskell
Prelude> :load Varfun.hs
Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>
現在你可以直接使用Varfun.hs中定義的函數了:
*Main> areaCircle 5
78.53981633974483
注意我們直接在GHCi中輸入的Haskell代碼和寫在文件中的有些不一樣,最主要的,就是在文件中定義符號和函數時,不需要(不能)在前面加let了。
比如,直接在GHCi中輸入的
let x = 3
let y = 2
let areaCircle r = pi * r ^ 2
在文件中要寫成
x = 3
y = 2
area r = pi * r ^ 2
在文件中可以少寫很多let,方便多了。至於為何GHCi直接輸入時要加let,是有道理的,以後我們會解釋的。
這是最主要的區別。除此以外,還有兩個你不一定會遇到的小區別。
在GHCi中,如果我們直接輸入:
Prelude> let y = x * 2
GHCi會報錯:
<interactive>:1:8: Not in scope: `x'
因為GHCi不知道x代表什麽,或者說GHCi找不到x的定義。
所以,在GHCi中,我們必須先給出x的定義:
Prelude> let x = 3
Prelude> let y = x * 2
但是在文件中,兩種寫法都可以:
y = x * 2
x = 3
x = 3
y = x * 2
因為GHCi會閱讀整個文件。順序是無關緊要的。
在文件中,這樣的寫法是不能成立的:
r = 5
r = 2
r這個符號有兩個相矛盾的定義,顯然不能成立。(并不存在什麽後面的定義覆蓋前面的定義之類的規則,Haskell程序中語句的順序是無關緊要的。)
但在GHCi中,這樣是可以的:
Prelude> let r = 5
Prelude> r
5
Prelude> let r = 2
Prelude> r
2
為什麽可以?將在以後解釋。
練習:
12.1 將你在以前的練習中所寫的函數寫到一個文件中。在GHCi中載入這個文件,測試你寫的函數。
答案
11.1
- 不成立。fst適用于tuple(pair),而[1,2]是list。
- 不成立。cons只適用於list,不適用於tuple。
- 不成立。cons只適用於list,不適用於tuple。
- 成立。 你將得到[(2,4)]。
- 不成立。(2,4)和(5,5)是兩個整數組成的tuple,而('a','b')是兩個字符組成的tuple,類型不同。
- 成立。