y組合子:\f.(\x.f(xx))(\x.f(xx)),接受乙個函式,返回乙個高階函式
y組合子用於生成匿名遞迴函式。
什麼叫匿名遞迴函式,考慮以下c語言遞迴函式
int sum(int n)這個函式在內部遞迴呼叫了自身,呼叫自身需要函式本體的名字,這個函式叫sum,sum內部用名字sum,遞迴呼叫了自己
在lambda演算中,可以寫成類似的表示式sum = \x. x == 0 ? 0 : sum x
但是對於乙個lambda表示式,他本身是匿名的,lambda在定義的過程中引用了自身,就算是c++,這樣的lambda表示式也是不成立的
auto sum = (int n) ;lambda表示式本身是不具名的,我們需要繞開這個限制。
一種可能的解決辦法是使用高階函式,用另乙個函式把上面的sum包裝一下:它接受乙個函式f,並返回乙個函式,這個函式接受x,判斷遞迴終點,或呼叫f繼續遞迴:
g = \f. \x. x == 0 ? 0 : f (x-1)
寫成c++是這樣的
auto g = (functionf) ;現在我們發現,當有乙個函式f使得g(f) = (int x) = f的時候,這個f正好是我們需要的匿名遞迴函式sum};
g(f) = f,眼熟嗎,還記得不動點這個概念嗎,我們需要的匿名遞迴函式sum就是函式g的不動點
求解這個不動點sum,我們即可獲得乙個匿名遞迴函式,如何求解見附
最後的結果:sum = yg,y和g前面已知,這樣,sum是乙個簽名為int(int)的函式,是乙個匿名遞迴函式
y組合子也稱不動點組合子,用這個方法可以求解一切匿名遞迴函式。
附:sum = yg使得g(sum) = sum的證明:
證明:對於任意g,g(yg) = yg
令w = \x. g(xx), x = ww //這個令真的太tm絕了,反正我是沒想到
有x = ww = (\x. g(xx))w = g(ww) = g(x)
又因為yg = (\x. g(xx))(\x. g(xx)) = ww = x
所以g(x) = x就是g(yg) = yg
證畢
lambda演算中的遞迴與Y組合子
考慮在 lambda 演算中實現乙個遞迴的階乘函式,f ac t n 1 n 0 n cdot fact n 1 n neq0 end fact n fib n begin 1 n 1 1 n 2 fib n 1 fib n 2 n notin end fib n 1 1fib n 1 fi b n...
Racket中使用Y組合子
關於y組合子,網上已經介紹很多了,其作用主要是解決匿名lambda的遞迴呼叫自己。首先我們來看直觀的遞迴lambda定義,假設要定義階乘的lambda表達,c 中需要這麼定義 func fact null fact x x 1 1 x fact x 1 這種方法非常簡單直接,當然問題也存在,因為這裡...
演算法 回溯求排列組合,子集問題的總結
leetcode上有許多用回溯求排列組合,子集的題目 leetcode46 leetcode47 我的思路可看這裡 leetcode77 我的思路可看這裡 leetcode39 leetcode40 leetcode216 leetcode78 leetcode90 我的思路可看這裡 總結一下 用回...