Haskell特性
- 簡潔的程序風(fēng)格
- 強大的類型系統(tǒng)
- List comprehensions(wiki的意思就是有基于存在的lists創(chuàng)建一個list的能力)
- 遞歸函數(shù)
- 高階函數(shù)(接受函數(shù)為參數(shù),返回值為函數(shù))
- Effectful函數(shù)(就是純函數(shù)的反義詞。Haskell提供了統(tǒng)一的框架來處理副作用)
- 泛型函數(shù)
- 惰性求值
- 等式推導(dǎo)
Haskell初體驗
以下只為體驗,不為詳解。
第一個例子神凑,求和函數(shù)
sum函數(shù)的定義
sum [] = 0 -- 等號左邊為函數(shù)聲明,右邊為函數(shù)體
-- 這里我們定義了一個函數(shù)sum,接受一個空列表為參數(shù),返回值為0
sum (n:ns) = n + sum ns --遞歸定義
-- (n:ns)為一個list帘瞭,n代表list中的第一個元素淑掌,ns代表list中除了第一個元素以外剩下的元素蒿讥,ns等于是子list
-- 這里相當(dāng)于重載了sum函數(shù)的定義,接受一個list為參數(shù)抛腕,返回值為:第一個元素 + 子列表的和(遞歸調(diào)用sum)
sum函數(shù)的類型
sum :: Num a => [a] -> a
-- 箭頭左邊限定a的類型為Num芋绸;箭頭右邊的為函數(shù)類型定義,即接受一個列表担敌,列表中的數(shù)據(jù)為a摔敛,返回值為a
sum函數(shù)的計算過程
sum [1, 2, 3]
-- 1. 根據(jù)函數(shù)定義可推導(dǎo)出 sum [1, 2, 3] = 1 + sum [2, 3]
-- 2. 以此類推 1 + sum [2, 3] = 1 + 2 + sum [3]
-- 3. 1 + 2 + sum [3] = 1 + 2 + 3 + sum []
-- 4. 1 + 2 + 3 + sum [] = 1 + 2 + 3 + 0 (根據(jù)函數(shù)定義sum [] = 0)
-- 5. 最后答案為6
第二個例子,快排函數(shù)
quicksort函數(shù)的定義
quicksort [] = [] --參數(shù)值為空列表時全封,返回值為空列表
quicksort (x:xs) = quicksort smaller ++ [x] ++ quicksort larger
where
smaller = [a | a <- xs, a <= x]
larger = [b | b <- xs, b > x]
-
++
操作符把兩個list連接起來马昙,[1,2,3] ++ [4,5] = [1,2,3,4,5] -
smaller
為子列表桃犬,在where
中做了限定,即smaller
中的元素a
行楞,取值于子列表xs
攒暇,且a的值小于等于x
。x為原始列表的第一個值子房。也就是說形用,smaller
這個子列表中的數(shù)據(jù)都比x
小或者等于x
- 同理,
larger
這個子列表中的數(shù)據(jù)都比x
來的大
quicksort函數(shù)的類型
quickesort :: Ord a => [a] -> [a]
-- 數(shù)據(jù)a限定為Ord類型证杭。該函數(shù)接受一個列表為參數(shù)田度,列表中的數(shù)據(jù)為a,返回一個列表解愤,列表的數(shù)據(jù)為a
quicksort函數(shù)的計算過程
quicksort [1]
-- 1. quicksort [] ++ [1] ++ quicksort [] (根據(jù)定義镇饺,比1小的列表為空,比1大的列表為空)
-- 2. [] ++ [1] ++ [] (根據(jù)定義琢歇,quicksort [] = [])
-- 3. 結(jié)果為[1]
quicksort [3, 4, 5, 1, 2, 3]
-- 1. quicksort [1, 2, 3] ++ [3] ++ quicksort[4, 5]
-- 2. (quicksort [] ++ [1] ++ quicksort [2, 3]) ++ [3] ++ (quicksort [] ++ [4] ++ quicksort [5])
-- 3. ([] ++ [1] ++ (quicksort [] ++ [2] ++ quicksort [3])) ++ [3] ++ ([] ++ [4] ++ [5])
-- 4. ([] ++ [1] ++ ([] ++ [2] ++ [3])) ++ [3] ++ ([] ++ [4] ++ [5])
-- 5. 結(jié)果為[1, 2, 3, 3, 4, 5]
第三個例子兰怠,帶有副作用操作的函數(shù)
seqacts函數(shù)的定義
seqacts函數(shù)接受一個列表,列表里是一系列輸入或者輸出操作李茫,比如在控制臺讀取或者寫入字符揭保。
seqacts [] = return [] -- 此return非彼return。這里的return為一函數(shù)魄宏,用于將值包裝進IO秸侣。因此此處的返回值為IO []
seqacts (act:acts) = do x <- act -- 當(dāng)列表不為空時,先運行第一個操作宠互,返回值為x
xs <- seqacts acts -- 對子列表繼續(xù)調(diào)用seqacts函數(shù)
return (x:xs) -- 返回值為IO [a]
seqacts函數(shù)的類型
通過上面的定義可以推導(dǎo)出類型為:
seqacts :: [IO a] -> IO [a]
-- 輸入輸出操作是有副作用的操作味榛,在Haskell中用IO表示副作用操作(這里可以把IO想成函數(shù))。而a表示副作用操作的返回值(函數(shù)的返回值)
-- 返回值是一個副作用操作予跌,這個副作用操作的返回值是一個列表搏色,列表中的數(shù)據(jù)為a(可以這樣想,返回值是個函數(shù)券册,這個函數(shù)的返回值是個[a])频轿。為什么這里不直接返回[a],因為seqacts函數(shù)涉及了IO烁焙,返回值則也要用IO包裝
IO也是有類型的航邢,因此函數(shù)類型可以進一步抽象為:
seqacts :: Monad m => [m a] -> m [a]
-- Monad就像上兩例中的Num和Ord
(完)