[TOC]
Haskell
GHCI
- 通過(guò)Tab可以自動(dòng)補(bǔ)全
- 通過(guò)
:browser 模塊名稱(chēng)
胎食,瀏覽該模塊下的函數(shù) -
:info 函數(shù)名
顯示函數(shù)相關(guān)信息 -
:set +t
每次輸出都會(huì)攜帶輸出類(lèi)型信息
標(biāo)準(zhǔn)庫(kù)函數(shù)
map
遍歷數(shù)組蹬耘,針對(duì)數(shù)組中的元素進(jìn)行映射轉(zhuǎn)換處理;映射轉(zhuǎn)換是有一個(gè)函數(shù)組成的
-- (\x -> x ^2 ) 表示定義了一個(gè)匿名函數(shù)(lambda 表達(dá)式)
-- 從[1..10] 這個(gè)數(shù)組中取出每一個(gè)元素,傳給匿名函數(shù)位岔,x則表示的就是傳入的元素
-- 針對(duì)傳入的元素做平方操作后放回到數(shù)組中
map (\x -> x ^2 ) [1..10]
-- out: [1,4,9,16,25,36,49,64,81,100]
filter
遍歷數(shù)組,針對(duì)數(shù)組中的元素進(jìn)行過(guò)濾判斷處理抒抬;過(guò)濾判斷函數(shù)必須返回值為Bool類(lèi)型
filter (\x -> x `mod` 3 == 0 ) [5..25]
-- out : [6,9,12,15,18,21,24]
lambda 表達(dá)式
用
\
作為開(kāi)始,并且需要用括號(hào)包裹妖胀;->
之前的是參數(shù),多個(gè)參數(shù)用空格分隔赚抡,之后的表示函數(shù)體纠屋;
關(guān)鍵字 fold
針對(duì)數(shù)組進(jìn)行左右折疊操作
foldl/foldr scanl/scanr
foldl 左折疊操作 foldr 右折疊操作
scanl 記錄折疊操作狀態(tài),相當(dāng)于是foldl的執(zhí)行過(guò)程記錄
foldl1 foldr1 相比f(wàn)old1 少了累計(jì)值售担,其實(shí)累計(jì)值用的是數(shù)組的第一個(gè)元素
scanl1 scanr1
-- foldl :: (b -> a -> b) -> b -> [a] -> b
-- (+) 對(duì)應(yīng) (b -> a -> b) 表示 加函數(shù) 對(duì)應(yīng) b 和 a兩個(gè)參數(shù)并且返回 b類(lèi)型
-- 0 對(duì)應(yīng) -> b 表示的是累計(jì)值
-- [1..10] 對(duì)應(yīng) -> [a] 表示的是數(shù)組
-- 輸出值 對(duì)應(yīng) -> b
-- 整體過(guò)程: 用 0+1的結(jié)果作為 累計(jì)值族铆,再加 2 ,依次類(lèi)推
foldl (+) 0 [1..10]
--out: 55
scanl (+) 0 [1..10]
--out: [0,1,3,6,10,15,21,28,36,45,55]
含有$ 的函數(shù)
$ 用來(lái)斷開(kāi)整個(gè)函數(shù)哥攘,以使得 $ 的右側(cè)先執(zhí)行,意義在于函數(shù)都是從左到右的優(yōu)先級(jí)献丑;
$ 的優(yōu)先級(jí)最低末捣,一定程度上可以減低括號(hào)的使用
-- 表示 5 * (2+7)
(*) 5 ((+) 2 7)
-- 兩者等同创橄,如去掉 $ 則無(wú)法正確執(zhí)行
(*) 5 $ (+) 2 7
-- out: 45
-- 此處表示用$ 可以將數(shù)據(jù)作為函數(shù)調(diào)用
map ($ 3) [(4+),(10*),(^2),sqrt]
-- out : [7.0,30.0,9.0,1.7320508075688772]
Function composition 函數(shù)組合
函數(shù)組合就是多個(gè)函數(shù)組合成一個(gè)串行的函數(shù)鏈,用 點(diǎn)號(hào)(.) 進(jìn)行連接邦邦;
組合函數(shù)是前一個(gè)函數(shù)的參數(shù)類(lèi)型需要同后一個(gè)函數(shù)的回傳值類(lèi)型一致
fx (fy (fz p)) 使用組合方式為 (fx . fy . fz) p醉蚁,fz p執(zhí)行后的返回值類(lèi)型需要同fy的參數(shù)類(lèi)型一致
不建議使用組合方式,形成復(fù)雜的函數(shù)鏈條网棍,可以拆分成多個(gè)子函數(shù)鏈,使用let綁定一個(gè)函數(shù)名稱(chēng)氏身,可以提高代碼可讀性
4 + (3*4)
-- 使用函數(shù)的方式編寫(xiě) $表示先執(zhí)行 3 *4
(+) 4 $ (*) 3 4
-- 使用點(diǎn)號(hào)組合函數(shù),組合函數(shù)
-- +4 和 *3 都是一個(gè)不完全函數(shù),相當(dāng)于是都只傳了一個(gè)參數(shù)的函數(shù)
-- 先將參數(shù) 4 傳給 *3 蛋欣,然后將結(jié)果 12 傳給 +4 ,所以得到16
((+4) . (*3)) 4
(+4) . (*3) $ 4
let sx = (+4) . (*3) in sx 4
-- out: 16
Module 模塊
模式是含有一組相關(guān)的函數(shù)到踏、型別和型別類(lèi)的組合尚猿;
-- import 用于在代碼中裝載模塊
-- qualified 顯示代碼中需要引用某函數(shù)時(shí)需要加上 Data.Map前綴,為了解決加載模塊中函數(shù)名沖突的情況
-- as M讹躯,則是簡(jiǎn)寫(xiě) Data.Map前綴 為M
import qualified Data.Map as M;
構(gòu)建模塊
-- 以hs文件名 構(gòu)建模塊
module fileName
( functionName1,
functionName2,
functionName3
) where
-- 以hs文件所在目錄缠劝,構(gòu)建子模塊
module fileDir.fileName
( functionName1,
functionName2,
functionName3
) where
構(gòu)建Types 和 Typeclasses
data Shape = Circle Float Float Float | Ractangle Float Float Float
Record Syntax
Type parameters 型別參數(shù)
類(lèi)似java 里面的泛型,針對(duì)型別不固定的情況惨恭,可以用型別參數(shù)的方式達(dá)到更好的通用性
-- Map 就是攜帶了 k v 兩個(gè)型別參數(shù)
import qualified Data.Map as Map
Derived instances
deriving (Eq, Ord, Show, Read, Bounded, Enum)
- Eq 比較
- Ord 排序
- Show 顯示成字符串
- Read 解析成具體的型別
- Bounded 邊界
- Enum 枚舉
Type synonyms
型別同義詞,相當(dāng)于給型別取了個(gè)別名
-- String 就是字符數(shù)組的別名
type String = [Char]
Recursive data structures (遞歸地定義數(shù)據(jù)結(jié)構(gòu))
在定義型別時(shí)萝究,值構(gòu)造子又使用了定義的型別锉罐,形成遞歸
-- 模擬標(biāo)準(zhǔn)庫(kù)中的List的遞歸
data List a = EmptyList | Cons { listHead:: a, listTail :: List a } deriving (Show,Read,Eq,Ord)