2017-04-03 2 views
2

Ich versuchte, die Kleisli Potenzierung in Kotlin zu schreiben:Kleisli Potenzierung in Kotlin

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

, die gerade f komponiert, n mal (bitte meinen Code nicht setzen n = 0 in).

Kotlin (1.0.6) klagt error: unsupported [References to variables aren't supported yet] zeigt auf die ::f.

Mache ich etwas falsch?

Antwort

3

Verwendung nur f statt ::f, es ist bereits ein Funktionswert (das heißt ein Parameter, eine Variable oder eine Eigenschaft eines funktionellen Typs), so dass Sie nicht einen aufrufbare Bezug daraus machen müssen.

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

Auch scheint Ihr Beispiel eine Typenkonflikt zu haben: kleisli(n - 1, f) eine Funktion vom Typ gibt (A) -> B, die auf it vom Typ A, Rückkehr ein Ergebnis vom Typ B genannt wird. Dann wird das Ergebnis an f übergeben, aber f kann nur A empfangen. Um dies zu beheben, können Sie Typparameter B und lassen Sie entfernen nur 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)


Auch dieser Code die Absicht sehr gut in funktionalen Stil zeigt, aber es könnte zur Folge haben, in Redundante Objektzuordnung und unerwünschtes Call-Stack-Wachstum. Es kann jedoch in einen imperativen Stil umgeschrieben werden, der effizienter arbeitet:

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

Vielen Dank! Das funktioniert. Scheint so, als müsste ich viel mehr über Kotlin wissen. Und es tut mir leid, dass ich f fehlt, um f zu komponieren, denn f muss a-> a sein. –

+0

Nur aus Neugier, was bedeutet dieser Fehler (Verweise auf Variablen werden noch nicht unterstützt)? –

+1

@ Koyomi-chan, '' f' würde, wenn es unterstützt würde, eine aufrufbare Referenz auf den Parameter 'f' der Funktion bedeuten - ein Objekt, das einige Informationen über diesen Parameter enthält und eine Möglichkeit bietet, seinen Wert zu erhalten. Es gibt bereits [Funktionsreferenzen] (http://kotlinlang.org/docs/reference/reflection.html#function-references) und [bound callable references] (https://gist.github.com/udalov/f86fbea722a53730f3f5777d871ab8ba) in Kotlin, beide mit '::'. Lokale Variablen- und Parameterreferenzen werden jedoch vorerst nicht unterstützt. – hotkey