2017-07-26 9 views
1

Kotlin FP(ラムダ、関数)を使ってY-コンビネータ関数を書くことはできますか? JSでコトリンを使ってY-コンビネータ機能を書くには?

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

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) -> (x x)) ((x) -> (f ((y) -> ((x x) y)))) 
[Function] 

coffee> fact = Y (f) ->(n) -> if n==0 then 1 else n*f(n-1) 
[Function] 

coffee> fact(10) 
3628800 

私はこれをどのように行うことができますか? Kotlinで

答えて

0

、あなたはKotlinがを静的例えば、プログラミング言語ではなく、動的言語を入力しているのでそうしないとあなたは、UNCHECKED_CAST警告を取得します、追加のインタフェースGを導入すべきである:

typealias X = (Int) -> Int 
typealias F = Function1<X, X> 
//  v-------------v--- let G reference G recursively 
interface G : Function1<G, X> 

// 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) } }) 

別のそれは例えば、UNCHECKED_CAST警告を抑制する必要がありますので、バージョンは、GFunction1<G, X>をキャスト:

typealias X = (Int) -> Int 
typealias F = Function1<X, X> 
typealias G = Function1<Any, X> 

@Suppress("UNCHECKED_CAST") 
//           v--- cast `g` to `G`. 
fun Y(f: F) = (fun(g: Function1<G, X>) = g(g as G))({ g -> f { x -> g(g)(x) } }) 

val fact = Y({ rec -> { n -> if (n == 0) 1 else n * rec(n - 1) } }) 
関連する問題