2017-04-03 134 views
2

我試着寫了Kleisli冪在科特林:Kleisli冪在科特林

fun <A,B> kleisli(n: Int, f: (A) -> B): (A) -> B = if (n == 1) f else { it -> f(kleisli(n-1, ::f)(it)) } 

,只是組成fn倍(請不要把n = 0在我的代碼)。

Kotlin(1.0.6)抱怨error: unsupported [References to variables aren't supported yet]指向::f

我做錯了什麼?

回答

3

使用的只是f代替::f,它已經是一個功能值(即一個參數,變量或功能型的屬性),所以你不需要做它的一個調用的參考。

... else { it -> f(kleisli(n - 1, f)(it)) } 

此外,您的例子似乎有一個類型不匹配:kleisli(n - 1, f)返回(A) -> B類型,這就是所謂的A類型的it,返回B類型的結果的功能。然後結果傳遞到f,但f只能收到A。爲了解決這個問題,你可以刪除類型參數B只有A離開:

fun <A> kleisli(n: Int, f: (A) -> A) : (A) -> A = 
    if (n == 1) 
     f else 
     { it -> f(kleisli(n - 1, f)(it)) } 

(runnable demo of this code)


此外,該代碼演示的意圖非常清楚的實用的風格,但它可能會導致成冗餘對象分配和不希望的調用堆棧增長。但是,它可以被重寫爲命令式,這將更有效地工作:

fun <T> iterativeKleisli(n: Int, f: (T) -> T) : (T) -> T = { x -> 
    var result = x 
    for (i in 1..n) 
     result = f(result) 
    result 
} 
+0

謝謝!這樣可行。似乎我需要更多地瞭解Kotlin。也很抱歉錯過了構成f,f需要是 - > a。 –

+0

只是爲了好奇,那個錯誤是什麼意思(引用變量還不支持)? –

+1

@Koyomi-chan,如果支持,':: f'將意味着對函數參數'f'的可調用引用 - 一個包含有關該參數的一些信息並提供獲取其值的方法的對象。已經有[函數引用](http://kotlinlang.org/docs/reference/reflection.html#function-references)和[綁定可調用引用](https://gist.github.com/udalov/f86fbea722a53730f3f5777d871ab8ba) Kotlin,都使用'::'。但現在不支持局部變量和參數引用。 – hotkey