邱奇數

邱奇編碼是把資料和運算子嵌入到 lambda 演算內的一種方式，最常見的形式即邱奇數，它使用 lambda 符號表示自然數。方法得名於阿隆佐・邱奇，他首先以這種方法把資料編碼到 lambda 演算中。

透過邱奇編碼，在其他符號系統中通常被認定為基本的項（比如整數、布林值、有序對、列表和 tagged unions）都會被對映到高階函式。在無型別 lambda 演算，函式是唯一的原始型別。

邱奇編碼本身並非用來實踐原始型別，而是透過它來展現我們不須額外原始型別即可表達計算。

很多學數學的學生熟悉可計算函式集合的哥德爾編號；邱奇編碼是定義在 lambda 抽象而不是自然數上的等價運算。

用途

直接實現邱奇編碼會將某些訪問操作的時間複雜度從降低到（其中是資料結構的大小），這使得該編碼方式在實際應用中受到限制。研究表明可以透過針對性最佳化解決這個問題，但大多數函數語言程式設計語言選擇擴充套件其中間表示以包含代數資料型別。

儘管如此，邱奇編碼仍常用於理論論證，因為它在部分求值和定理證明中具有自然表示優勢。透過使用高階型別可以對操作進行型別標註，並能便捷地實現原始遞迴。由於函式被假定為唯一的原始資料型別，這種設定簡化了許多證明過程。

邱奇編碼具有表示完整性但僅限於表徵層面。需要額外函式將這種表示轉換為通用資料型別以供人工解讀。由於邱奇定理中等價性不可判定，通常無法判斷兩個函式是否具有外延等價性。轉換過程可能需要透過某種方式應用函式來提取其表徵值，或者以 λ 項字面量的形式查詢其值。λ 演算通常被解釋為使用內涵等價性。由於等價性的內涵定義與外延定義存在差異，在結果解釋方面可能存在潛在問題。

邱奇數

邱奇數為使用邱奇編碼的自然數表示法，而用以表示自然數的高階函式是個任意函式對映到它自身的 n 重函式複合之函式，簡言之，數的「值」即等價於引數被函式包裹的次數。

不論邱奇數為何，其都是接受兩個引數的函式。邱奇數 0、1、2、... 在 λ 演算中的定義如下：

從 0 不應用函式開始， 1 應用函式一次， 2 應用函式兩次， 3 應用函式三次，依此類推：

邱奇數 3 表示對任意給定函式應用三次的操作。當輸入函式被提供時，首先應用於初始引數，然後連續應用於自身結果。最終結果並非數字 3（除非初始引數恰好為 0 且函式為後繼函式）。邱奇數 3 的本質是函式的應用次數，而非計算結果本身。其核心意義在於「重複三次」的動作，這正是「三次」概念的直觀體現。

就是說，自然數被表示為邱奇數 n，它對於任何 lambda - 項 F 和 X 有著性質：

 n F X =β Fn X。

2.1 使用邱奇數的計算

在 lambda 演算中，數值函式被表示為在邱奇數上的相應函式。這些函式在大多數函式式語言中可以透過 lambda 項的直接變換來實現（服從於型別約束）（請參閱將 lambda 表示式轉換為函式）。

加法函式 利用了恆等式 。

後繼函式 β- 等價於（plus 1）。

乘法函式 利用了恆等式 。

指數函式 透過邱奇數定義給出：將定義中的和代入可得，因此：

對應的 lambda 表示式為：

前驅函式 的實現較為複雜：

邱奇數透過 n 次應用函式來運作。前驅函式需要返回一個應用引數 n-1 次的函式。這透過構建包含 f 和 x 的容器來實現，該容器以省略第一次函式應用的方式初始化（詳見前驅函式推導）。

基於前驅函式可定義減法函式：

2.2 邱奇數函式一表

注意：

2.3 前驅函式推導

邱奇編碼中使用的前驅函式定義為：

為了減少一次函式應用次數來構造前驅函式，需採用容器函式封裝值。定義新函式 和 替代原函式和引數，其中容器函式稱為。下表左側展示了邱奇數作用於和的情況：

通用遞迴規則為：

若定義從容器中提取值的函式：

則可構造同數函式：

透過將替換為特殊容器（該容器首次呼叫時忽略引數以跳過第一次函式應用），可推導前驅函式：

具體函式定義如下：

最終得到前驅函式的 lambda 表示式：

2.3.1 前驅函式的另一種解釋

使用組合子符號可簡化前驅函式的解釋：

透過下列推導可驗證其正確性：

透過 eta - 歸約和歸納法可得：

2.3.2 前驅函式的另一種定義

使用序對可定義前驅函式：

此定義雖簡潔但展開式較複雜，以為例：

2.4 除法函式

自然數除法可透過以下方式實現：

計算需要多次 beta 歸約。除非手動進行歸約，否則這並不重要，但最好避免重複計算。最簡單的數值檢測謂詞是 IsZero，故考慮條件：

此條件等價於而非。若採用該條件，則上述數學定義可轉化為邱奇數函式：

此定義僅呼叫一次，但結果為此公式給出的是的值。

透過給 n 加 1 後呼叫 divide 可修正該問題，定義式為：

divide1 為遞迴定義，需用 Y 組合子實現遞迴。透過以下步驟建立新函式 div：

左側替換：
右側替換：

得到：

完整定義式為：

其中：

:

最終展開式：

以文字格式表示（用 \ 代替 λ）：

divide = (\n.((\f.(\x.x x) (\x.f (x x))) (\c.\n.\m.\f.\x.(\d.(\n.n (\x.(\a.\b.b)) (\a.\b.a)) d ((\f.\x.x) f x) (f (c d m f x))) ((\m.\n.n (\n.\f.\x.n (\g.\h.h (g f)) (\u.x) (\u.u)) m) n m))) ((\n.\f.\x. f (n f x)) n))

例如，9/3 可表示為：

divide (\f.\x.f (f (f (f (f (f (f (f (f x))))))))) (\f.\x.f (f (f x)))

使用 lambda 演算計算器，按正規順序歸約後結果為 3：

\f.\x.f (f (f (x)))

2.5 有符號數

透過使用包含正負值的邱奇序對，可將邱奇數擴充套件至有符號數。整數值即兩個邱奇數的差值。

自然數轉有符號數的定義為：

取反操作透過交換序對元素實現：

當序對中某一元素為零時，整數表示更自然。OneZero 函式確保該條件：

使用 Y 組合子實現遞迴：

2.6 加減運算

加法數學定義為：

對應 lambda 表示式：

減法定義為：

對應 lambda 表示式：

2.7 乘除運算

乘法定義為：

對應 lambda 表示式：

除法需確保序對元素含零（見上文的 OneZero），定義輔助函式：

除法表示式：

2.8 有理數與實數

有理數可表示為有符號數序對，可計算實數可透過極限過程編碼。複數可自然地表示為實數序對。上述資料型別驗證了邱奇 - 圖靈論題：任何資料型別或計算均可編碼於 lambda 演算中。

2.9 換成其它表達法

大部分真實世界的程式語言都提供原生於機器的整數，church 與 unchurch 函式會在整數及與之對應的邱奇數間轉換。這裡使用 Haskell 撰寫函式， \ 等同於 lambda 演算的 λ。 用其它語言表達也會很類似。

type Church a = (a -> a) -> a -> a

church :: Integer -> Church Integer

church 0 = \f -> \x -> x

church n = \f -> \x -> f (church (n-1) f x)

unchurch :: Church Integer -> Integer

unchurch cn = cn (+ 1) 0

邱奇布林值

邱奇布林值是布林值真和假的邱奇編碼形式。某些程式語言使用這個方式來實踐布林算術的模型，Smalltalk 和 Pico 即為典型示例。

布林邏輯本質上是選擇機制。邱奇布林值的編碼形式為接收兩個引數的函式：

真（true）選擇第一個引數
假（false）選擇第二個引數

其標準定義為：

這種編碼允許謂詞函式（返回邏輯值的函式）直接作為條件語句使用。當布林函式作用於兩個引數時，將根據真值返回其中一個引數：

若 predicate-x 為真則返回 then-clause，否則返回 else-clause。

由於真值與假值的選擇特性，它們可組合出各類邏輯運算子。需注意邏輯非 not 存在多種實現方式：

註：

1 求值策略使用應用次序時，這個方法才正確。
2 求值策略使用正常次序時，這個方法才正確。

運算示例解析：

謂詞

謂詞是返回布林值的函式。最基礎的謂詞是，當其引數為邱奇數時返回，否則返回：

下列謂詞檢測第一個引數是否小於等於第二個引數：

基於恆等關係：

相等性檢測可定義為：

邱奇序對

邱奇序對是二元組的邱奇編碼實現。序對被表示為接收函式的函式，當傳入引數時會將該引數作用於序對的兩個分量。其 lambda 演算定義為：

示例推導：

列表編碼

不可變的列表由列表節點構成，其基本操作包括：

以下給出四種不同的列表表示法：

使用雙序對構造列表節點（支援空列表）
使用單序對構造列表節點
基於右摺疊函式的列表表示
採用 Scott 編碼的模式匹配引數化表示

6.1 雙序對列表節點

非空列表可用邱奇序對錶示：

First 儲存首元素
Second 儲存尾部

為支援空列表，需額外包裹序對形成三層結構：

First - 空列表識別符號
Second.First 儲存首元素
Second.Second 儲存尾部

基於此的核心操作定義如下：

注意：當列表為空時，head 和 tail 函式不應被呼叫。

6.2 單序對列表節點

另一種定義方式 PDF 版本：：

通用處理模板定義為：

6.3 右摺疊列表表示

作為邱奇序對編碼的替代方案，列表可透過其右摺疊函式進行編碼。例如，包含三個元素 x、y、z 的列表可編碼為高階函式，當該函式應用組合子 c 和初始值 n 時，返回 c x (c y (c z n))。這等價於部分應用函式組合鏈的呼叫：(c x ∘ c y ∘ c z) n。

此列表表示可在系統 F 型別系統中定義。

與邱奇數的對應關係並非巧合，邱奇數本質上是單元值列表（如 ）的一進位制編碼，列表長度即表示自然數值。對此類列表進行右摺疊時，組合函式忽略元素值，其本質與邱奇數中的函式組合鏈（即 (c ∘ c ∘ c ) n = (f ∘ f ∘ f) n）具有等價性。

6.4 Scott 編碼列表表示

另一種實現方式是採用 Scott 編碼，這種方式能生成更簡潔的程式碼（參見摩根森 - 斯科特編碼）。

該編碼的核心思想是利用模式匹配的特性。以 Scala 語法為例，假設 list 表示包含空列表 Nil 和構造器 Cons (h, t) 的列表型別，可透過模式匹配進行計算：

list match {case Nil => nilCode

case Cons (h, t) => consCode (h,t)

}

列表的行為由其模式匹配決定，因此可將列表定義為接收 nilCode 和 consCode 引數的函式：

設 n 對應空列表處理引數，c 對應非空列表處理引數，則：

空列表定義為：

非空列表（含首元素 h 和尾部 t）定義為：

更一般地，包含種構造器的代數資料型別將被編碼為具有個引數的函式。當第個構造器包含個引數時，對應編碼引數也接收個引數。

該編碼可在無型別 λ 演算中使用，但帶型別版本需支援遞迴和型別多型的系統。以元素型別 E、計算結果型別 C 的列表為例，其遞迴型別定義為（"=>" 表示函式型別）：

type List =

C => // 空列表分支

(E => List => C) => // 非空列表分支

C // 模式匹配結果

支援任意計算型別的列表需量化型別 C，而泛型列表還需將元素型別 E 作為型別引數。