函數(shù)式編程中不動(dòng)點(diǎn)函數(shù)原理和實(shí)現(xiàn)

感覺關(guān)于不動(dòng)點(diǎn)函數(shù)的講解網(wǎng)上沒有說的特別清楚的,我來解釋一下。
首先不動(dòng)點(diǎn)函數(shù)解決的是遞歸問題,準(zhǔn)確的說是匿名函數(shù)的遞歸問題,匿名函數(shù)沒有函數(shù)名稱很難直接自己構(gòu)建遞歸關(guān)系,所以需要依賴不動(dòng)點(diǎn)函數(shù)來進(jìn)行遞歸。

我們用乘法計(jì)算來舉例,通過加法遞歸來實(shí)現(xiàn)乘法
普通的實(shí)現(xiàn)如下:
f(x,0)=0
f(x,y)=x+f(x,y-1)

當(dāng)然這在具備函數(shù)名的時(shí)候很容易實(shí)現(xiàn)
function mult(x,y){
if (y==0){
return 0
}else{
x+mult(x,y-1)
}
}

在匿名函數(shù)時(shí)就比較困難了,首先因?yàn)闊o法利用自己遞歸,我們需要引入一個(gè)外部函數(shù)

function anonymousMult(f,x,y){
if (y==0){
return 0
}else{
x+f()(x,y-1)
}
}

其中如果要實(shí)現(xiàn)遞歸關(guān)系f()的執(zhí)行結(jié)果就要滿足如下函數(shù)形式
anonymousMult f
這樣才能滿足遞歸條件

這樣核心問題就變成了構(gòu)建f這樣一個(gè)函數(shù),而這個(gè)函數(shù)就是不動(dòng)點(diǎn)函數(shù)

這個(gè)函數(shù)的形式如下
λf.(λs.(f (s s)) λs.(f (s s)))(anonymousMult)

代入anonymousMult =>
(λs.(anonymousMult (s s)) λs.(anonymousMult (s s)))

執(zhí)行一下(將右邊的λs.(anonymousMult (s s))代入左邊表達(dá)式的λs)變?yōu)?br> anonymousMult(λs.(anonymousMult (s s)) λs.(anonymousMult (s s)))

滿足了上面提到的遞歸條件

我們可以用3*2作為例子演示一下
λf.(λs.(f (s s)) λs.(f (s s)))(anonymousMult) (3,2)=>

anonymousMult((λs.(anonymousMult (s s)) λs.(anonymousMult (s s))),3,2){
if (2==0){
return 0
}else{
3+(λs.(anonymousMult (s s)) λs.(anonymousMult (s s)))()(3,1)
}
} =>

3+anonymousMult((λs.(anonymousMult (s s)) λs.(anonymousMult (s s))),3,1) =>

3+anonymousMult((λs.(anonymousMult (s s)) λs.(anonymousMult (s s))),3,1){
if (1==0){
return 0
}else{
3+(λs.(anonymousMult (s s)) λs.(anonymousMult (s s)))()(3,0)
}
} =>

3+3+anonymousMult((λs.(anonymousMult (s s)) λs.(anonymousMult (s s))),3,0)=>

3+3+anonymousMult((λs.(anonymousMult (s s)) λs.(anonymousMult (s s))),3,0){
if (0==0){
return 0
}else{
3+(λs.(anonymousMult (s s)) λs.(anonymousMult (s s)))()(3,-1)
}
} =>

3+3+0=6

完成

具體的程序?qū)崿F(xiàn)如下,因?yàn)橐呀?jīng)有了函數(shù)式,我們要做的就是構(gòu)建具體的函子
第一個(gè)函子是(s s)

實(shí)現(xiàn)如下:
function applicative(s){
return function() {return s(s)}
}

第二個(gè)函子是
λf.(λs.(f (s s)) )

實(shí)現(xiàn)如下:
function self(recursiveFunc){
return function (s){
f=applicative(s);
return recursiveFunc(f)}
}

通過這兩個(gè)函子就可以構(gòu)建不動(dòng)點(diǎn)函數(shù)(不動(dòng)點(diǎn)函數(shù)又叫Y函子)

function lamdaY(func){return self(func)(self(func))}

最后我們代入一個(gè)匿名函數(shù)就可以執(zhí)行了

假設(shè)計(jì)算3*4

lamdaY(function(func){return function(x,y){if(y==0){return 0}else{return x+func()(x,y-1)}}})(3,4)

得到結(jié)果12

同樣的,計(jì)算斐波那契數(shù)

lamdaY(function(func){
return function(x){
if(x==0){return 0}
else if(x==1){return 1}
else {
return func()(x-1)+func()(x-2)
}
}
})(10)

得到結(jié)果55

實(shí)現(xiàn)完成

關(guān)于函數(shù)式編程的理論,建議閱讀
Greg Michaelson寫的
AN INTRODUCTION TO FUNCTIONAL PROGRAMMING THROUGH LAMBDA CALCULUS
整體解釋的非常完整

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容