這樣的功能往往在固定點組合遇到。例如Y combinator的一種形式被寫爲λf.(λx.f (x x)) (λx.f (x x))
。定點組合器用於在無類型lambda演算中實現一般遞歸,而無需任何額外的遞歸構造,這是使非類型化lambda演算Turing-complete成爲可能的一部分。
當人們開發simply-typed lambda calculus,這是一個天真的靜態類型系統的頂端lambda微積分,他們發現,這是不可能寫出這樣的功能。事實上,在簡單類型的lambda演算中不可能執行一般的遞歸;因此,簡單類型的lambda演算不再是圖靈完備的。 (一個有趣的副作用是,在簡單類型的演算程序總是終止。)
實時靜態類型的編程語言,如標準ML需要內置的遞歸機制來克服這一問題,如命名的遞歸功能(用val rec
或fun
定義)並命名爲遞歸數據類型。
它仍然可以使用遞歸數據類型來模擬你想要的東西,但它不是很漂亮。
基本上,你想定義類型如'a foo = 'a foo -> 'a
;但是,這是不允許的。你,而不是把它包在一個數據類型:datatype 'a foo = Wrap of ('a foo -> 'a);
datatype 'a foo = Wrap of ('a foo -> 'a);
fun unwrap (Wrap x) = x;
基本上Wrap
和unwrap
使用'a foo
和'a foo -> 'a
之間轉換,反之亦然。
無論何時您需要調用函數本身而不是x x
,您都必須明確編寫(unwrap x) x
(或unwrap x x
);即unwrap
將其變成可以應用於原始值的功能。
P.S.另一個ML語言OCaml有一個選項來啓用遞歸類型(通常是禁用的);如果您使用-rectypes
標誌運行解釋器或編譯器,則可以編寫諸如fun x -> x x
之類的內容。基本上,在幕後,類型檢查器計算出需要「包裝」和「解開」遞歸類型的位置,然後將它們插入到您的位置。我不知道任何具有類似遞歸類型功能的標準ML實現。
如果任何人有興趣,我發現這被稱爲[U Combinator(見頁面底部)](http://www.ucombinator.org/),但無法找到更多關於它的信息。 – 2012-02-06 16:09:08
我不知道它被稱爲U combinator,但正如該頁面所述,它用於構建我在答案中提供的無類型lambda微積分的(顯然最短的)非終止程序。 – 2012-02-06 16:18:48