最簡單的函數
函數式編程,首先要有函數吧,來看一個最簡單的函數,第一個是函數名,後面是輸入變量,表達式是輸出
doubleMe x=x+x
-
Haskell的函數沒有
return
語句,最後一句話是自然的返回值,函數都要保存爲文件,文件以.hs結尾。 -
讀取編寫好的文件(以.hs結尾)
:l 文件名
List 數據結構
LIST基本操作
- List中各個元素的類型需要一致
- 使用 let XXX = [1,2,3,4,5]進行聲明
- 字符串也是一個List
-
使用
:
添加新元素,如5 : [1,2,3,4]
將5添加到List中,可以加在之前或者之後 -
使用
!!
來獲取List索引的數據,如[1,2,3,4]!!2
結果是2
-
head
返回第一個元素,tail
返回除了第一個以爲的後面元素 -
last
返回最後一個元素,init
返回除最後一個元素的前面其他元素 -
length
返回list長度 -
null
檢查list是否爲空,爲空返回True
-
reverse
反轉一個List -
take
返回list的前幾個元素take 2 [1,2,3,4]
-
drop
刪除前幾個元素 -
maximum
返回list最大值,minmum
返回最小值 -
sum
求和 -
elem
判斷元素是否在list中,使用中綴表達式4 \
elem` [1,2,3,4]`
RANGE操作
-
使用
..
來生成大量連續數據,如[1..100]
-
可以使用前兩個元素來表示步長,如
[1,3...100]
生成100內的奇數 -
Haskell支持無限長的List,如
[1,2..]
,Haskell是惰性語言,只有在運行的時候纔會去求值,所以支持無限長序列 -
cycle
用來循環一個List,生成一個無限長的List,如cysle [1,2,3]
,將生成[1,2,3,1,2,3..]
-
repeat
用來重複一個數據,並生成一個無限長List,如repeat 3
將生成[3,3,3,3,3..]
LIST的包含和過濾
Haskell是函數式編程語言,所以有一些我們之前在普通編程語言中不一樣的東西,Haskell更接近數學描述,比如數學集合中的comprehension
。
List可以這麼寫:
[x*2 | x <- [1..10]]
這個List將返回[2,4,6,8,10,12,14,16,18,20],很顯然,|
左邊是表達式,右邊是集合,將集合[1..10]
分別賦值給x,然後進行x*2
的運算,產生一個新的List。
對於上面那個式子,我們還可以修改一下,加一些約束,這個叫過濾
[x*2 | x <- [1..10], x*2 >= 12]
這樣,返回的是[12,14,16,18,20]了,只有表達式>=12纔會輸出
來些實在的
好,我們來個複雜的,寫一個函數,函數名爲testfunc,在輸入的集合中找出所有大於10並且除以3餘2的所有奇數,並且將找出來的這些奇數都乘以5
testfunc abc=[ x*5 | x<-abc,x>10,x `mod` 3==2,odd x]
好,把這個保存爲一個.hs結尾的文件func.hs。然後打開ghci
終端,輸入:l
func
,運行 testfunc [20..60],結果將輸出[115,145,175,205,235,265,295]
,怎麼樣,簡單把,你想想用命令式的編程語言(比如C語言)實現這個將如何寫?呵呵
好吧,再來個難一點的,找出給定序列中的所有素數,先想想C語言怎麼寫,我來寫個Haskell的,爲了好看,我把一行的內容分開到幾行了。
primeNum inNum=[x| x<- inNum,
odd x,
sum[1|_<-[y|y<-[2..x-1],
x `mod` y == 0]
]==0
]
在命令行輸入:
primeNum [3..100]
輸出結果爲:
[3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
對,就一行,我來解釋一下,inNum是輸入序列,先判斷是否是奇數,然後從2到x-1重新生成一個序列賦值給_
,_
表示我們不關心值是什麼,然後x取模y如果等於0,就輸出一個1,否則不輸出,輸出的新序列求和,如果和等於0,表示沒有一個x取模y等於0,表示這是一個素數,那麼就把這個x輸出出來。聽起來挺繞口吧,仔細體會一下就明白了,你會發現函數式編程比命令行更接近我們的思維和數學模型。
Tuple(元組)數據結構
從某種意義上講,Tuple (元組)很像 List –都是將多個值存入一個個體的容器。但它們卻有着本質的不同,一組數字的 List 就是一組數字,它們的類型相同,且不關心其中包含元素的數量。
- Tuple 則要求你對需要組合的數據的數目非常的明確,它的類型取決於其中項的數目與其各自的類型。
- Tuple 中的項 由括號括起,並由逗號隔開。
- 另外的不同之處就是 Tuple 中的項不必爲同一類型,在 Tuple 裏可以存入多類型項的組合。
-
fst
返回元組的第一個元素fst(8,11)
,返回8 -
snd
返回元組的最後一個元素 -
zip
函數,通過兩個List生成元組List,兩兩集合,比如zip [1,2,3] [4,5,6]
將生成[(1,4),(2,5),(3,6)]
不同長度的List通過zip組合按照短的那個List組合
來些實在的
我們有這麼一個要求,在每條邊都小於100的三角形中,找出所有直角三角形,並列出三條邊的長度,首先,你還是想想用C語言怎麼寫這個程序,我還是來個haskell的。
[(a,b,c) | a<-[1..100],b<-[1..a],c<[1..b],c^2+b^2==a^2]
恩,還是一行搞定,都不需要函數了。
本教程參考了《Haskell趣學指南》,是這篇指南的學習筆記,不過參入了我自己的一些想法和總結,首先,感謝《Haskell趣學指南》的作者bonus 和大陸翻譯者Fleurer和臺灣翻譯者MnO2,謝謝你們之前的工作。