1 Polymorphic Types
在很多情況下帜慢,不同的數(shù)據(jù)類型會有相同功能的函數(shù)瘦真,例如判定相等或者不等绰播,List的append等等花枫。如果我們對每一個都單獨定義的話刻盐,會產(chǎn)生非常多的功能一致但只有類型不同的函數(shù)。在這種情況下劳翰,polymorphic type就顯得十分有用敦锌。
例如 reverse 函數(shù), 他將一個list顛倒過來佳簸。 我們希望它對各種類型都適用那么就可定義:
reverse::[a] ->[a]
注意此處 a 即任意一種類型乙墙,[a]是顯式的指明它為一個List型的類型。但是a也可以為List,[a]可以為以一種類型的list的list伶丐。
再比如說zip悼做,
zip::[a]->[b]->[(a,b)]
此處a,b可以為一種類型,也可以為不同類型哗魂。
2 Higher-order functions
先簡單介紹一下普通的function肛走。
最基本的函數(shù)其類型是:
T->R
T,R指任意類型,T為函數(shù)的參數(shù)录别,R為函數(shù)的輸出值朽色。
在函數(shù)定義時,例如higher-order function组题, 我們可以不必再原始定義中給出參數(shù)葫男,而是在第一次需要參數(shù)時給出定義。例如我們有函數(shù)
f::(a->a)->(a->b)->a->b
f func1 func2 = func3
? ? ? ? ? ? ? ? ? ? ? ? ? where func3 input = if func1 input then func2 input
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? else input
在函數(shù)定義的最初崔列,我們并沒有定義 input(函數(shù)參數(shù))梢褐,但是這并不影響函數(shù)定義的合法性。 我們在func3中調用了它赵讯。這么做可以提高程序可讀性盈咳。
另外,如果在函數(shù)中應用了lambda expression, 我們也可以在函數(shù)中省略參數(shù)边翼,這只是一個參數(shù)聲明的平移鱼响,因為我們還會在第一次用到參數(shù)時定義它。例如:
f::Int->Int
f = (\x->x+x)
雖然我們沒有以正常的f x =..來定義函數(shù)组底,但是在anonymous function中我們還是給出了定義丈积。
Haskell中,所有的函數(shù)都接收一個參數(shù)债鸡,返回一個值江滨。那么如何解釋之前寫過的接收多個參數(shù)的函數(shù)?
----它們被稱之為Curried functions(哎娘锁,我也不知道為什么Haskell有這么多和食物有關的術語牙寞,可能大佬是個吃貨吧)。
舉一個簡單的例子---
引用Learn You a Haskell for Great Good!?
http://learnyouahaskell.com/higher-order-functions
max:: Int->Int->Int
我們不管這個函數(shù)如何實現(xiàn)莫秆,總之它會選出兩個數(shù)之中較大的一個间雀。
這個函數(shù)接收第一個參數(shù)后,會返回一個接收Int的函數(shù)镊屎,最終返回a惹挟。
另一種寫法為 a->(a->a), 看,它返回的是一個函數(shù)缝驳!
如果我們定義一個函數(shù)是 f = max 3,我們再調用f的時候连锯,實際上是把缺少的一個參數(shù)補給了max归苍。
這種應用函數(shù)的方法為 --- partial application。
回到Higher order functions來运怖,對應只接受一個參數(shù)的函數(shù)它是first order,剩余的即higher order拼弃。higher order中會以函數(shù)作為參數(shù),在函數(shù)定義中以括號標識出來摇展,例如:
f:: (a->a)->b->(a,b)
(a->a)即以個以a為參數(shù)返回a的函數(shù)吻氧。
3 Lambda-abstractions
Lambda abstractions實際上是為了創(chuàng)造anonymous function,可以在定義函數(shù)之間方便的構造一個新的輔助函數(shù)咏连。它的大概形式如下:
(\x -> x + x) x盯孙; (\x y -> x+y) x y
括號中為函數(shù)的定義,括號外緊跟的為函數(shù)的輸入祟滴,它會替代所有x(在\x->中)振惰,或者二元的話就將對應替代---第一個數(shù)對應第一個參數(shù),第二個對應第二個參數(shù)垄懂。
稍微復雜點的形式可以是嵌套的
大致為: \x-> (\y..) 這實際上為f.y
一個復雜一點的例子:
map (\x -> (map (\y->(x,y)) [1..10])) [0..9]
map函數(shù)對[0..9]的每一個元素都調用了中間的函數(shù)骑晶,而中間的關于x的函數(shù)是關于另一個map的函數(shù),這個map中又有關于y的函數(shù)草慧。它實際上等效于list:
[(x,y)|x<-[0..9],y<-[1..10]]
值得注意的一點是透罢,transition的關系只有在括號的嵌套之中才有,如果是括號之外的另外一個anonymous function冠蒋,那么就無任何關系,例如:
((\x-> x+1) 2) + ((\x->x+2) 3)
它的輸出為8.
4 Higher order function 與? list
所有的list乾胶,都可以由concat,filter,map函數(shù)構造出來抖剿。
例如:
original = [ (x,y) | x <- [1..100], y <- [1..x], x `mod` y > 0 ]
它可以被改寫為:
alternative = concat (map(\x->(map (\y->(x,y)) (filter (\y-> x`mod`y>0) [1..x]))) [1..100])
需要提醒的一點是,在\x->之后的括號中都為關于x的函數(shù)识窿,所以x可以被用于任何一個子函數(shù)中斩郎,但是filter,map為分開的兩個函數(shù),所以關于y的兩個函數(shù)并無關聯(lián)喻频。
5 List Function
以list為參數(shù)的function需要注意函數(shù)的non-exhaustive即詳盡性或者全面性缩宜。
使用x:xs迭代性可避免各種各樣的pattern match缺失。
6 ':' operator 與 '++' operator
':' operator 與 '++' 都是返回list的operator甥温,但是:
':'? 它接受一個任意類型參數(shù)加一個此類型的list參數(shù)锻煌,具體來講是把一個參數(shù)放到一個list的首位。即類似: 1:[2,3,4] = [1,2,3,4] 或者 [1,2]:[[3,4],[5,6]] = [[1,2],[3,4],[5,6]]
a->[a]->[a]
'++': 它接受兩個list類型參數(shù)姻蚓,并把第二個連入第一個的尾部宋梧。即類似:
[1,2] ++ [3,4] = [1,2,3,4]
[a]->[a]->[a]