Kleisli在Kotlin求幂
我试图写下Kotlin的Kleisli指数:
fun <A,B> kleisli(n: Int, f: (A) -> B): (A) -> B = if (n == 1) f else { it -> f(kleisli(n-1, ::f)(it)) }
只是组成f
, n
次(请不要在我的代码中加n = 0
)。
Kotlin(1.0.6)抱怨error: unsupported [References to variables aren't supported yet]
指向::f
。
我做错了什么?
使用f
而不是::f
,它已经是一个函数值(即一个参数 ,一个变量或者一个函数类型的属性),所以你不需要对它做一个可调用的引用。
... else { it -> f(kleisli(n - 1, f)(it)) }
另外,你的例子似乎有一个类型不匹配: kleisli(n - 1, f)
返回类型(A) -> B
的函数, it
的类型A
调用,返回类型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)) }
(此代码的可运行演示)
而且,这个代码在功能方面表现得非常好,但是可能会导致冗余的对象分配和不希望的调用堆栈增长。 但是,它可以被改写成势在必行的风格,这将更有效地工作:
fun <T> iterativeKleisli(n: Int, f: (T) -> T) : (T) -> T = { x -> var result = x for (i in 1..n) result = f(result) result }