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