Processing math: 100%

2021年12月1日 星期三

國中生就會 y-combinator

國中的時候大家都做過一個題目:
2+2+2+=?
這題目的做法是令2+2+2+=x  ,接下來都會做了,兩邊都平方,就變成 2+x=x2。其實也可以左邊加2再取根號,意思一樣。這裏當然有一個假設沒跟國中生講,就是2+2+2+會收斂到一個數。
 
於是引出了一個概念,叫做函數的不動點。如果 f(x)=xx 就叫 f 的不動點。很多時候,代一個不等於 x,但是跟 x 相近的數,例如 y,也可以求出 f 的不動點,方法就是 f(f(f(...f(y)))),這會收斂到 x 。看起來很熟悉!不論你是在做國中題目,還是實用上在計算最大值,都是在做這件事而已。
 
不動點應用到計算理論上(以現代觀點來講,可以直接當成就是在講程式語言了),就是假設 f 對任意數的任意次迭代 (例如f(f(f(3)))就是 f 對 3 的3次迭代) 都有定義。那麼我們就認為 f(f(f()))也代表一個函數,稱之為 g,是 f 的「不動函數」,也簡稱不動點。計算理論上因為函數的回傳值常常也是函數,所以用前置式寫法比較方便。例如前面的 f(3) 用前置式寫法就是 (f 3)
 
於是有了 f,我們要求 g 到底怎麼表示。所以跟國中的算法一樣
(f(f(f...)))=g
兩邊再取 f 可以得到
(f g)=g
 
實際上我們沒辦法直接得到 g,要藉由另一個函數 R,以 f 當成輸入,回傳值就是 g,所以
(R f)=g
代入式(1)得到
(R f)=(f (R f))
這就是 R 的定義,R 就是大名鼎鼎的 y-combinator。
什麼!居然這麼簡單?用的只是國中的技法!
有的時候巧妙的計算只是想法轉個彎而已,內涵並不複雜。不過就這個彎可能要想幾十年。原始的y-combinator是數學家Haskell提出的,他的版本看起來比 R 複雜很多,可是可以簡化成 R

沒有留言: