如何使用Kotlin编写Y-combinator函数?

我可以使用Kotlin FP(Lambda,函数)编写Y组合函数吗?

Y = λf.(λx.f (xx)) (λx.f (xx)) 

在JS中:

 function Y(f) { return (function (g) { return g(g); })(function (g) { return f(function (x) { return g(g)(x); }); }); } var fact = Y(function (rec) { return function (n) { return n == 0 ? 1 : n * rec(n - 1); }; }); 

在咖啡:

 coffee> Y = (f) -> ((x) -> (xx)) ((x) -> (f ((y) -> ((xx) y)))) [Function] coffee> fact = Y (f) ->(n) -> if n==0 then 1 else n*f(n-1) [Function] coffee> fact(10) 3628800 

我怎样才能做到这一点?

在Kotlin中,你应该引入一个额外的接口G ,否则你将得到UNCHECKED_CAST警告,因为Kotlin是一种静态types的编程语言而不是动态语言,例如:

 typealias X = (Int) -> Int typealias F = Function1 // v-------------v--- let G reference G recursively interface G : Function1 // v--- create a G from lazy blocking fun G(block: (G) -> X) = object : G { // v--- delegate call `block(g)` like as `g(g)` override fun invoke(g: G) = block(g) } fun Y(f: F) = (fun(g: G) = g(g))(G { g -> f({ x -> g(g)(x) }) }) val fact = Y({ rec -> { n -> if (n == 0) 1 else n * rec(n - 1) } }) 

另一个版本将一个Function1投射到G ,所以它应该抑制UNCHECKED_CAST警告,例如:

 typealias X = (Int) -> Int typealias F = Function1 typealias G = Function1 @Suppress("UNCHECKED_CAST") // v--- cast `g` to `G`. fun Y(f: F) = (fun(g: Function1) = g(g as G))({ g -> f { x -> g(g)(x) } }) val fact = Y({ rec -> { n -> if (n == 0) 1 else n * rec(n - 1) } })