Haskell 筆記(二)List和元組

最簡單的函數


函數式編程,首先要有函數吧,來看一個最簡單的函數,第一個是函數名,後面是輸入變量,表達式是輸出

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,謝謝你們之前的工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章