Download - Haskell Foundations

Transcript
Page 1: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

函數程式語言: Haskell 基礎

黃耀賢

[email protected]微程式技術研討會

October 22, 2008

1 / 30

Page 2: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Outline

1 起頭 (Beginning)

2 Lambda Calculus

3 有型態的 Lambda Calculus (Typed)

4 Haskell 基礎 (Basics)

5 小結 (Subtitle)

6 參考文獻 (Bibliography)

2 / 30

Page 3: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Leibniz 的理想

1 通用語言:創造一種語言,使能描述各種問題。

Frege 和 Russell 等數學家,以初階述語邏輯所描述的集合論形式解決。

2 決策問題:找到一種決策法,將所有以通用語言描述的

問題解決。

為一哲學問題:「能夠以通用語言解答所有難題嗎?」,號稱為

Entscheidungsproblem /Ent"S2IdUNs�pô6bl@m/ (德語,意為「決策問

題」)。

3 / 30

Page 4: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Entscheidungsproblem 求解

同時由 Church 與 Turing 各自證為否定。為了證明,需要下列工具

• Lambda calculus:Alonzo Church 在 1936 年發明的正式系統,並定義可執行函數的標記法。

• Turing machines:Alan Turing 在 1936 年 7 月發明的機器類型,並定義可執行函數的標記法。

同年,Turing 證明二種模型有同樣強度,是由於定義了相同的可執

行函數。

4 / 30

Page 5: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Turing machines 的發展

Figure: Turing Machine 的藝術式圖現。1

• Von Neumann 計算機以 Turing machine 概念為基礎。

• 命令程式語言,包括組合語言、 Fortran 、 Pascal 等等都根據 Turing machine 接受指令的方式而出現。

1圖摘自 http://en.wikipedia.org/wiki/Turing machine gallery5 / 30

Page 6: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Lambda calculus 的發展

• Alonzo Church 在 1936 年提出 lambda calculus 正式系統,並定義可執行函數的標記法。

• Haskell Brookes Curry 和 Alonzo Church 先後在 1934 年和 1940 年介紹有型態的 lambda calculus 。

• 函數程式語言,包括 Miranda 、 ML 、 Haskell 等等都根據 lambda calculus 而出現。

• Lisp 是較早期的例子,但混雜一些其他概念。

• Reduction machines 由函數程式的執行而出現。

6 / 30

Page 7: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

算式的構成

• Lambda calculus 的算式都表達為函數,由 Lambda

Term (lambda 詞彙) 構成。

• 任意變數就是 lambda term 。例如: x

x ′

• 一些 lambda term 放在一起,也是 lambda term。例如: x x ′

(x x ′) y z

• 以“λ 變變變數數數. lambda term”格式構成的詞彙,也是lambda term。例如: λx . x (lambda abstraction , lambda 抽象化)

λx y . x y

7 / 30

Page 8: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

算式的性質

• 範圍: “λ x .M”格式的 lambda term ,存在於 M 中的 x

都是「受限制的」(bound)。例如:x ((λx. x + 1)y) z ′

x 是受受受限限限制制制的的的變變變數數數。

• 不受限制的變數稱為自自自由由由變變變數數數(free variable)。

• 封封封閉閉閉的的的 lambda 詞詞詞彙彙彙:若一則 lambda 詞彙中沒有自由變數(意思是所有的變數都受限制),是封閉 lambda詞彙(closed λ term)。

• 不是封閉 lambda 詞彙的,是開開開放放放的的的 lambda 詞詞詞彙彙彙(open

λ term)。

8 / 30

Page 9: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Combinator

• 如果一則 lambda 詞彙是封閉的,就是一個 combinator

• Identity combinator I ≡ λx . x。

• K ≡ λxy . x。

• K∗ ≡ λxy . y。

• S ≡ λxyz . x z (y z)。

• Fixpoint combinator Y ≡ λf . (λx . f (x x)) (λx . f (x x)) 使∀F .F (YF ) = YF。

9 / 30

Page 10: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Reduction (簡化、約化)

• 令E為構成一函數程式的式子,E可以有一些改寫規則。

Reduction 是將P,E的一部份,根據改寫規則取代為另

一個式子P ′,簡列為:

E [P ] → E [P ′]

• 可可可化化化簡簡簡的的的式式式子子子: λ 開頭的式子和其他參數放在一起,如

(λv .M)N,就可以化簡。

• 例如: (λxy . s x y) u v −→ s x y [x := u, y := v ] ≡ s u v

10 / 30

Page 11: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

完全化約 (Full Reduction)

• 完完完全全全化化化約約約(full reduction)任何可化簡的式子可在任何時候化簡。

• 例如:

id(id(λz .id z)) → id(λz .id z)

→ id(λz .z)

→ λz .z

11 / 30

Page 12: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

一般化約 (Normal Order Strategy

Reduction)

• 一一一般般般化化化約約約(normal order strategy)最外邊、最左邊的可化簡式先化簡。

• 例如:

id(id(λz .id z)) → id(λz .id z)

→ λz .id z

→ λz .z

12 / 30

Page 13: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Call By Name

• Call by name較嚴格,不容許在抽象化的 lambda 詞彙(即 λ 開頭的 lambda 詞彙)中做化約。

• 例如:

id(id(λz .id z)) → id(λz .id z)

→ λz .id z

• Call by name又稱為 lazy evaluation。

• Haskell採用優化的 lazy evaluation,所有相同的 lambda詞彙,第一個已經化簡的就儲存起來,後續的詞彙直接

參考第一個化簡的結果,而節省重複的化簡動作。

13 / 30

Page 14: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Call By Value

• Call by value由最外邊的可化約式,並要先將參數化

約。

• 例如:

id(id(λz .id z)) → id(λz .id z)

→ λz .id z

• Call by value又稱為 strict evaluation。

• (λbfg . if b then f else g) b f g 的化約不能做

call-by-value ,必須做 call-by-name 。

14 / 30

Page 15: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

建立數字計算系統

1 定義 true ≡ K 和 false ≡ K∗。

2 定義選擇結構 [M, N] ≡ λz . z M N ,其中 z M N 表示

if B then Melse N。於是,

[M, N] true = M

[M, N] false = N

Proof.[M, N] true ≡ (λz . z M N) (λxy . x)= z M N[z := (λxy . x)] ≡ (λxy . x)M N

= x [x := M, y := N] ≡ M

15 / 30

Page 16: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

建立數字計算系統(續)

3 遞迴定義數字,將每個自然數 n 的數字定義為 pnq :

p0q = I

pn + 1q = [false, pnq]

4 定義零和前後關係:

S+pnq = pn + 1q

P−pn + 1q = pnq

Zero p0q = true

Zero pn + 1q = false

Proof.S+ ≡ λx . [false, x ]P− ≡ λx . x false

Zero ≡ λx . x true

16 / 30

Page 17: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

建立數字計算系統(續)

• 想定義加法運算如

Add(0, y) = yAdd(x+1, y) = 1+Add(x, y)

• 意思和這個 lambda 詞彙相同:Add x y = if Zero x then y else S+(Add (P− x) y)

• 用 Y combinator 製作遞迴:

Add ≡ Y(λaxy . if Zero x then y else S+(a (P− x) y))

17 / 30

Page 18: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

簡單型態系統

• 型態系統由 H. B. Curry 在 1934 年介紹,之後 1958 年和 1972 年做了一些改變,用自然的方式推導 lambdaterm 的型態。

• T 為型態的集合。

• 任何 lambda term M 都可以被指派為一個型態 σ ,只要

σ ∈ T。

• 函數套用:M : σ → τ N : σ

M N : τ

• 函數抽象化:

x : σ...

M : τ

λx .M : σ → τ

18 / 30

Page 19: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

Haskell 簡介

1 發明於 1987 年,以 Haskell Brookes Curry 為名。

2 Haskell 98 標準之後,舊版語言已拋棄。

3 Haskell 是有有有型型型態態態的函函函數數數式式式程式語言。

4 以 standard prelude 為預設標準函式庫。

5 有關資訊請參考 http://haskell.org。2

2http://haskell.org/ghc 為 GHC (一種 Haskell 98 的實作) 發佈的網站,提供了 Windows 、 Linux 、 Solaris 和 Mac OS 版本的安裝程式。

19 / 30

Page 20: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

資料值 (Value) 和型態

• Haskell 預設下列資料型態:• 5 :: Integer

• ’K’ :: Char

• False :: Bool• [3,2,1] :: [Integer]

• (’b’, True) :: (Char, Bool)

• id :: a -> a

id x = x

• 測測測定定定型型型態態態(Typing):“::〈Type〉” 是「有· · ·型態」的意思,會做型態的建立和檢查。

20 / 30

Page 21: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

基本型態

• Bool

• Char:用單引號圍起的字母。

• String:即一列 Char 資料,用雙引號圍起的許多字

母。 ”Hello” 就是 [’H’,’e’,’l’,’l’,’o’] 。

• Int:固定精確度的整數,值介 −231 ∼ 231 − 1 之間。

• Integer:任意精確度的整數。

• Float:單精確度的浮點數。

• List 型態:用方括號包含型態標記為指定型態,構成 list型態。 [Int] 是整數型態的 list 型態。

• Tuple 型態:用圓括號包含逗點分隔的多個型態,構成tuple 型態。 (Int, Int) 是一對整數型態的 tuple 型態。

• 函數型態:用 -> 箭頭連接多個型態,構成函數型態。

Int -> Int 是從一個整數型態對應到另一個整數型態

的函數型態。

21 / 30

Page 22: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

自訂型態

• 語法:

data Type-constructor = Data-constructors

• 定義「顏色」型態:

data Color = Red | Orange | Yellow

| Green | Blue | Indigo | Violet

• 定義「點」型態:只有一個 data constructor ,必須參考其他型態來建立型態。

data Point a = Pt a a

22 / 30

Page 23: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

「樹」資料結構

• data Tree a = Leaf a | Branch (Tree a) (Tree a)

• flatten :: Tree a -> [a]

flatten (Leaf x) = [x]

flatten (Branch x y) = flatten x ++ flatten y

• 練習:

1 將上述「樹」展平程式打字輸入在文字檔 test.hs ,存檔。

2 確定 GHC 已安裝。3 在命令列模式視窗中,切換到 test.hs 所存放位置,執行 ghci。

4 在 GHCi 環境輸入 :l test.hs 載入程式。若回應錯誤訊息請

檢查程式碼。

5 在 GHCi 環境輸入 flatten (Branch (Branch (Leaf ’a’)

(Leaf ’b’)) (Leaf ’c’)) 並觀察結果。

6 在 GHCi 環境輸入 :q 關閉 GHCi 環境。

23 / 30

Page 24: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

效能瓶頸

• (++) :: [a] -> [a] -> [a]

[]++ys = ys

(x:xs)++ys = x:(xs++ys)

• data Tree a = Leaf a | Branch (Tree a) (Tree a)

• flatten :: Tree a -> [a]

flatten (Leaf x) = [x]

flatten (Branch x y) = flatten x ++ flatten y

• 計算複雜度是 O2。

24 / 30

Page 25: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

減少 ++ 的計算量

• 利用累累累積積積變變變數數數(accumulating argument)減少 ++ 的計算量。

• 令 flatten′ t acc = flatten t ++ acc ,

• flatten′ (Leaf x) acc= { 由 flatten′ 的定義, }

flatten (Leaf x) ++ acc= { 套用 flatten }

[x] ++ acc= { 套用 ++ }

x:acc

25 / 30

Page 26: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

減少 ++ 的計算量(續)

• flatten′ (Tree x y) acc= { 由 flatten′ 的定義 }

flatten (Tree x y) ++ acc= { 套用 flatten }

(flatten x ++ flatten y) ++ acc= { 由 ++ 的結合律 }

flatten x ++ (flatten y ++ acc)= { 將 x 歸納 }

flatten′ x (flatten y ++ acc)= { 將 y 歸納 }

flatten′ x (flatten′ y acc)

26 / 30

Page 27: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

減少 ++ 的計算量(末)

• 於是,

flatten′ :: Tree a -> [a] -> [a]flatten′ (Leaf x) acc = x:accflatten′ (Tree x y) acc = flatten′ x (flatten′ y acc)

27 / 30

Page 28: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

小結和摘要

本次討論,我們知道了:

• 函數語言的源頭是 lambda calculus ,相對於命令式語言的源頭是 Turing machines.

• Lambda calculus 定義了詞彙的構成與化簡規則。藉此可以建立數學計算系統。

• Lambda 詞彙可以附加型態,並有合理的型態推導規則。

• Lambda calculus 的化簡有幾種策略,包括完全化簡、一般化簡、 call-by-name 和 call-by-value 。

• Haskell 是有型態的函數語言。從基本的資料值開始,每個詞彙都可以合理地推導型態。

• Haskell 容許以關鍵字 data 自訂型態。

28 / 30

Page 29: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

將來的內容

將來會談論的項目有:

• 運算元。

• 類別。

• Haskell 的標準函式庫 (standard prelude) 。

• 以 lambda 詞彙方式撰寫 Haskell 程式。

• 以數學方式撰寫 Haskell 程式。

• 區域變數。

• 高階函數。

• 輸入和輸出。

29 / 30

Page 30: Haskell Foundations

函數程式語言: Haskell

基礎

黃耀賢

起頭(Beginning)

LambdaCalculus

有型態的LambdaCalculus(Typed)

Haskell 基礎(Basics)

小結(Subtitle)

參考文獻(Bibliography)

參考文獻

1 Benjamin C. Pierce. Types and Programming Language. MIT, 2002.

2 Graham Hutton. Programming in Haskell. Cambridge, 2007.

3 Henk Barendregt and Erik Barendsen. Introduction to Lambda

Calculus. [Online] Available:ftp://ftp.cs.kun.nl/pub/CompMath.Found/lambda.pdf (Oct, 2008).

4 Hal Daume III. Yet another Haskell tutorial. [Online] Available:http://www.cs.utah.edu/ hal/docs/daume02yaht.pdf (Oct, 2008).

5 Paul Hudak, John Peterson, and Joseph Fasel. A gentle introduction

to Haskell: Version 98. [Online] Available:

http://www.haskell.org/tutorial/ (Oct, 2008).

30 / 30


Top Related