Ruby 實(shí)現(xiàn)多態(tài),用匹配子來理解類型理論——類型論(二)

目錄:
- Haskell 類型系統(tǒng)的不足
- Ruby 函數(shù)多態(tài)的類型實(shí)現(xiàn) | 類型 與 Matchy,參數(shù) 與 Serie
- 實(shí)現(xiàn) 參數(shù)數(shù)量的多態(tài)
Haskell 的函數(shù)的類型如下,它可以實(shí)現(xiàn)類型多態(tài)
我們把這六個(gè)分支叫做函數(shù)的分態(tài) 或者 分支函數(shù)。
但我們不可以進(jìn)行如下定義:
因?yàn)?Haskell 的所有函數(shù)本質(zhì)都是一元函數(shù),這是它實(shí)現(xiàn) 函數(shù)curry(柯里)化 的理論和原理。
二元函數(shù)接受一個(gè)值,返回一個(gè)一元函數(shù)。
因?yàn)?func 接受一個(gè) int 值之后,無法確定 要返回 int 還是 int -> int、
因此,Haskell 無法完美實(shí)現(xiàn) 參數(shù)數(shù)量的多態(tài)。
我們要實(shí)現(xiàn) 更完全 的多態(tài),不能使用 函數(shù)純一元 的設(shè)定。
如 Ruby 要實(shí)現(xiàn)數(shù)量多態(tài)是這樣的。
如下,是一個(gè)合法的 Ruby 函數(shù)定義和其調(diào)用。
我們把定義部分的?(a, b, c, *args, &blk),叫做 匹配子(Matchy)
而調(diào)用部分的 (a, b, c, d, e) 叫做?Serie(系列)。
blk.call(...)中的(a, b, [c, *args].sum) 叫做 打包(Packy)
Serie 需要通過 匹配子 匹配成功后,才能成功地調(diào)用 函數(shù)。
之后 Serie 經(jīng)過 打包,傳輸給 函數(shù)體進(jìn)行處理。
這里,匹配子 等同于 函數(shù)的類型。
Serie -> Matchy -> Packer -> Proc
之后 Proc 再輸出 Serie 給調(diào)用這個(gè)函數(shù)的函數(shù)。
為方便起見,匹配子的書寫為 Matchy(...)
系列的書寫為 Serie(...)

現(xiàn)在,我們要在 Ruby 中實(shí)現(xiàn)復(fù)雜的函數(shù)多態(tài)系統(tǒng)。
這是我自己寫的一個(gè)庫(kù)。

著手用 Ruby 實(shí)現(xiàn)函數(shù)多態(tài)
我們可以在 Ruby 中 定義函數(shù)多態(tài),以代替在函數(shù)內(nèi)部重復(fù)書寫的 if-else,
以及每次增加新功能都要增改函數(shù)定義、或者 給原函數(shù)起別名 的麻煩。
其中 Numeric, Numeric, Numeric => Numeric是 匹配子。
這個(gè)匹配子包含了返回值類型,用以根據(jù)調(diào)用它的下游函數(shù)所需要的參數(shù)類型,返回特定的分態(tài)。
可以看到,偽關(guān)鍵字?main 表示函數(shù)的主函數(shù),而 mu 則表示分支函數(shù)。這個(gè)main 和 mu 在具體的實(shí)現(xiàn)上只是一種語法鹽,方便理清關(guān)系。
Numeric, Numeric, Numeric 是函數(shù)的輸入匹配子。
=> 右邊的 Numeric 是函數(shù)的返回匹配子。
這表明,log 如果接受三個(gè) Numeric 參數(shù),以及下游調(diào)用者需要一個(gè) Numeric 參數(shù)
則?調(diào)用 模式為 Matchy( Numeric, Numeric, Numeric => Numeric )的分支函數(shù) 進(jìn)行計(jì)算。
(但是目前只實(shí)現(xiàn)了參數(shù)多態(tài),尚未實(shí)現(xiàn)返回值多態(tài))
可知,Numeric 是一個(gè)類(Class),而 1, 2, 3 是他的實(shí)例。
在Ruby 中,任何類的類都是類類(Class),都是Class 的實(shí)例,而任何不是類的對(duì)象,都可以當(dāng)作值。
Ruby 的模式匹配是
類類的實(shí)例?匹配?他的實(shí)例,即,類?匹配于 其 實(shí)例。
類類 匹配?類。
可以看到
Class 不是 任何非類實(shí)例的超父類
1. 類自身?無法匹配 類自身
2. 類? ? ? ??可以匹配 類實(shí)例
3. 非類實(shí)例? 可以? 匹配? 非類實(shí)例自身
如何讓 Numeric 匹配 Numeric?呢
這時(shí),需要指示 匹配函數(shù),match(matchy, serie),matchy 中的類當(dāng)作非類實(shí)例看待。
Just(Numeric) 可以匹配 Numeric
目前還沒有實(shí)現(xiàn) in 的這個(gè)功能。
Just(Numeric) 等價(jià)于?Numeric 的單例類。所以可以匹配成功。
理論上,匹配子?1, 2?表示匹配1 和 2的實(shí)例。而 1 和 2 不是類,顯然沒有實(shí)例。
但在Ruby中,非類實(shí)例 的匹配其自身。
因此不需要寫 Just(1), Just(2),Matchy(1, 2) 就可以 匹配 Serie(1, 2) 了。

參數(shù)數(shù)量標(biāo)記,用 正則表達(dá)式 來理解
Numeric {3} 表示 接收三個(gè)連續(xù)的 Numeric 實(shí)例
Numeric * 表示接受0個(gè)或多個(gè)連續(xù)的 Numeric 實(shí)例
在 Ruby 中的寫法是
Some(quant, class) 指示 匹配0到2個(gè)連續(xù)的 Float 實(shí)例
當(dāng)輸入的參數(shù)?Serie 匹配于?Matchy(Float, Some(..2, Float))時(shí),就會(huì)調(diào)用該函數(shù)。

那么,假設(shè) 函數(shù)對(duì) 參數(shù)的部分順序并不關(guān)心,該如何描述呢?
例如,加法,排序函數(shù)。
無論輸入的參數(shù)是怎樣的順序,輸出的結(jié)果都是一樣。

下回:更復(fù)雜的類型實(shí)現(xiàn):
- 交換律、結(jié)合律、冪律....
- 類型的并、單匹配子,母匹配子,子匹配子,匹配子的解繭。