1. 程式人生 > >Haskell心得(1) 模式匹配、高階函式、組合函式

Haskell心得(1) 模式匹配、高階函式、組合函式

摘要:介紹了haskell的幾種定義函式方式:模式匹配、高階函式、函式組合

  haskell是一種強型別的函數語言程式設計語言。haskell裡面,型別是一個核心的問題。但作為函數語言程式設計的普遍特性,高階函式是首先要考察的。除了高階函式和組合函式之外,模式匹配尤其是列表的匹配是haskell的獨特優點,另外point-free風格也是比較有趣的。

  模式匹配是指,函式的引數有多種可能的形式,呼叫時自動找到匹配的形式並呼叫。通常只用一個小寫字母表示引數而沒有特殊形式的模式稱為萬能模式,可以匹配除了特殊形式的任意的引數。列表和元組屬於haskell的基本資料結構,常在模式匹配裡使用。下面的階乘函式是一個最簡單的例子。引數或者為任意正整數,或者為0。

factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n-1)

  下面是元組和列表的模式匹配。函式呼叫時按照元組和列表的形式選擇合適的模式。

addX :: (Double, Double) -> (Double, Double) -> Double
addX (x1, _) (x2, _) = x1 + y1
length' :: [a] -> Int
length' [] = 0
length' (x:[]) = 1
length' (x:xs) = 1 + length' xs

  下面是定義函式的一些特殊形式,包括哨位(guard)、where、let、case。guard可以使函式在滿足不同條件時得到不同的值,這些條件以“|”區分。case類似,實際上case就是模式匹配。where和let是函式定義時區域性作用域中繫結變數或者函式。

max' :: (Ord a) => a -> a -> a
max' a b
   | a < = b
   | otherwise = a
addF :: [a] -> [a] -> a
addF s1 s2 = f1 + f2
  where (f1:_) = s1
        (f2:_) = s2
areaC :: Double -> Double
areaC x =
  let square = x * x
  in pi * square
find' :: [(Double, Double)] -> [Double]
find' xs = [xsi | (x1, x2) <- xs, let xsi = x1 * x2, xsi < 100]
head' :: [a] -> a
head' xs = case xs of [] -> error "empty"
                      (x:_) -> x

  下面的例子是定義快速排序函式。

quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
    let small = [a | a <- xs, a <= x]
        large = [a | a<- xs, a> x]
    in quicksort small ++ [x] ++ quicksort large
  高階函式是函數語言程式設計必不可少的特性。跟scheme一樣,最常用的就是map、filter、foldr、foldl等。它們將集合視為整體,強調的是對集合的整體操作,而遮蔽了迴圈迭代等在資料結構的微觀層面上的操作。
map :: (a -> b) -> [a] -> [b]
map _ [] =[]
map f (x:xs) = f x : map f fs
filter :: (a -> bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
  | p x       = x : filter p xs
  | otherwise = filter p xs
foldl :: (a -> b -> b) -> b -> [a] -> b
foldl f b0 [] = b0
foldl f b0 (x:xs) = foldl f (f x b0) xs
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f b0 [] = b0
foldr f b0 (x:xs) = f x (foldr f b0 xs)  
  haskell有一些特殊形式可以簡化函式的表達。例如$符號,其實就是改變左結合的函式呼叫為右結合。
($) :: (a -> b) -> a -> b
f $ x = f x
sum (filter (> 10) (map (*2) [1..10]))
sum $ filter (> 10) $ map (*2) [1..10]

這兩個表示式是等效的。另外還有一種重要的符號“.”表示函式組合。簡潔的表達了將一個函式呼叫後的值傳遞給另一個函式作為引數。

(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \x -> f (g x)
replicate 2 (product (map (*3) (zipWith max [1,2] [4,5])))
replicate 2 . product . map (*3) $ zipWith max [1,2] [4,5]
這也是兩種等效的寫法。

  最後舉個例子來說明point-free風格。

sum' :: (Num a) => [a] -> a
sum' xs = foldl (+) 0 xs
sum' = foldl (+) 0
上下兩種sum'的寫法是等同的,唯一的區別是省略了xs這個引數。結合“$”和“.”,free-point能使程式碼更簡潔,更關注於程式碼的邏輯抽象本身,而非針對資料的具體操作過程。

  注:本文程式碼示例大部分來自《haskell趣學指南》。



相關推薦

Haskell心得1 模式匹配高階函式組合函式

摘要:介紹了haskell的幾種定義函式方式:模式匹配、高階函式、函式組合   haskell是一種強型別的函數語言程式設計語言。haskell裡面,型別是一個核心的問題。但作為函數語言程式設計的普遍特性,高階函式是首先要考察的。除了高階函式和組合函式之外,模式匹配尤其是列

perl學習3模式匹配與正則表達式

.... 表達式 正則表達 pos 匹配模式 模式匹配 $2 多個 info 一:模式匹配中的特殊字符 1:  點號 .     匹配任何單個字符(換行符\n除外) 2:  反斜線 \     轉義字符,用於特殊符號前,使其失去特殊字符的作用變成普通字符 3:  +   

spark學習1--ubuntu14.04集群搭建配置jdk

RM int 5.0 java_home 輸入 str cas Go 比較 環境:ubuntu14.04 1、文本模式桌面模式切換 ctrl+alt+F6 切換到文本模式 ctrl + alt +F7 /輸入命令startx切換到桌面模式 2、更改Ip地址、主機名 /

MySQL常用操作1設置更改root密碼連接MySQLMySQL常用命令

mysql常用操作 設置更改root密碼設置mysql的root用戶密碼:(默認為空)1.查看mysql任務是否開啟:ps aux |grep mysql若無開啟則-->/etc/init.d/mysqld start2.登錄mysql : /usr/local/mysql/bin

redis集群與分片1-redis服務器集群客戶端分片

服務器集群 包含 工作 direct 數據丟失 網站 這一 線性 取模 下面是來自知乎大神的一段說明,個人覺得非常清晰,就收藏了。 為什麽集群? 通常,為了提高網站響應速度,總是把熱點數據保存在內存中而不是直接從後端數據庫中讀取。Redis是一個很好的Cache工具

大資料之scala --- 模式匹配,變數宣告模式,樣例類,偏函式,泛型,型變,逆變,隱式轉換,隱式引數

一、模式匹配:當滿足case條件,就終止 ---------------------------------------------------------- 1.更好的switch var x = '9'; x match{ case

微信掃碼登陸1---掃碼登入流程講解獲取授權登陸二維碼

掃碼登入流程講解、獲取授權登陸二維碼 具體流程可以看微信官網的掃碼登入文件 其實官方文件已經講的非常清楚而且講的也很明白。 一、掃碼登入流程講解 1、首先準備工作 網站應用微信登入是基於OAuth2.0協議標準構建的微信OAuth2.0授權登入系統。 在進行微信OAuth2.在進行微信OAut

Pandas個人操作練習1建立dataframe及插入列行操作

個人分類: Python 使用pandas之前要匯入包: import numpy as np import pandas as pd import random #其中有用到random函式,所以匯入 一、dataframe建立 pandas.DataF

scala習題14——模式匹配和樣例類

14.1 JDK發行包有一個src.zip檔案包含了JDK的大多數原始碼。解壓並搜尋樣例標籤(用正則表示式case [^:]+:)。然後查詢以//開頭幷包含[Ff]alls?thr的註釋,捕獲類似// Falls through或// just fall thr

整合產品開發IPD理論學習心得1

        對於很未接觸過整合產品開發(IPD)的人來說,“整合產品開發”這個名詞很容易讓人誤以為是“系統整合”範疇內的事情或工作。事實上,IPD是一個“軟體開發管理”層面的概念和方法。接下來的工作與IPD(整合產品開發)有直接關係,但IPD對我來說,完全是一個新概念、新

虛擬儲存器1——虛存概念及頁頁表和地址翻譯基礎

一、前言         虛擬儲存器,感覺很難,至少說很複雜,裡面涉及到的東西也比較枯燥。當然,如果能徹底搞清楚,對繼續學習作業系統原理是百利無一害的。         玩C或C++的人,經常通過&a的方式獲取變數地址,並將其賦值給指標變數,也通常用printf打

【QT】除錯心得1

1、報錯“filed has incomplete type QIcon”。 前向宣告的類或結構體只能用來定義指標或引用。 例如: private: QIcon * m_iconStart; QIcon *m_iconStop; (*

python學習心得1 --- 大型檔案的讀取

我在部落格上發表一些我的Python學習心得,希望對大家能有幫助。 這一篇我們講述大型檔案python如何去讀取。 1、檔案讀取 當我們使用open函式取得一個檔案物件之後,對這個檔案的所有操作都是通過這個控制代碼來實現的。 讀取檔案的操作有三

ACM做題心得1

left 資料結構裡最熟悉的就是樹這一部分,雖然很久沒有敲過了,但還是比較有親切感~ 借用了以前的程式碼,改動了一些,可以執行出結果,奇怪的是總是出現了Memory Limit Exceed(程式執行時超過題目允許的最大記憶體),多次改動後仍沒有解決問題……哪位仁兄有空可以幫忙看一下哈~~不勝感激! 以下是

scheme心得1 continuation與陰陽謎題

摘要:簡要介紹了scheme語言中continuation的用法。解釋了陰陽謎題程式的執行過程與結果。 Scheme是一種lisp方言,個人比較常用的執行環境是MIT-GNU Scheme。 今天談一談Continuation,是scheme的一種特性。一個有趣而神祕的應用

QT學習心得1--初學者

目前學習QT,我想實現按一個按鈕,調出檔案的對話方塊,選中檔名,供我進一步操作。可以在該按鈕對應的Slot函式中加入以下語句: QString s=QFileDialog::getOpenFileName("/anni123/project","AnyFile(*.*)",t

《現代作業系統》心得1

今天在辦公室,看到一個同事在xp的電腦上,從U盤往一個D盤拷貝東西,可是每當他複製資料夾下的2000多張圖片的時候,就彈出一個對話方塊“explore 記憶體引用不能為read”。然後整個電腦就卡死了,連工作管理員都都呼叫不出來了。 以前碰到這種

python 學習心得1〖笨方法學python〗

宣告:這是我學《笨方法學python》前14習題總結出來的方法,如有意見請在下方寫下評論或加QQ1693121186 歡迎一起討論技術問題哦 列印變數的方法 方法 1. 程式碼如下: age

Object 物件方法學習之1—— 使用 Object.assign 複製物件合併物件

作用Object.assign() 方法用於把一個或多個源物件的可列舉屬性值複製到目標物件中,返回值為目標物件。語法Object.assign(target, ...sources)引數target: 目標物件sources: 源物件返回值目標物件描述Object.assign 方法只複製源物件中可列舉的屬性

JavaScript高階程式設計第3版學習心得1

語法 一、在html中加入JavaScript: 1.在html中嵌入JavaScript程式碼 <script type="text/javascript"> if(1<2){ alert('jjjj'); } </scri