我正在使用此更高阶的撰写功能:
fun <T, U, V> higherCompose(): ((U) -> V) -> ((T) -> U) -> (T) -> V =
{ f ->
{ g ->
{ x -> f(g(x)) }
}
}
应用程序:
val cos = higherCompose<Double, Double, Double>()()
{ x: Double -> Math.sin(x)}() { x : Double -> Math.PI/2 - x }
我确实了解我们在数学上想要达到的目标。但是我正在努力的是符号和编程含义:
确切是
higherCompose<Double>()
为什么我们要对其应用如此奇怪的值:
1. () ()
2. { function1} { function 1}
答案 0 :(得分:1)
以下是解析此表示法的方法以及函数调用的内容:
higherCompose<Double, Double, Double>()() { x -> Math.sin(x) }() { x -> Math.PI/2 - x }
| ^| ^ ^^^^^^^^^^^^^^^^^^^| ^ ^^^^^^^^^^^^^^^^^^^^^^|
| 1| 2 3 | 4 5 |
|_____________________________________|______________________|_________________________|
| first call | second call | third call |
这是对higherCompose
的初始无参数调用,该调用返回与higherCompose
的返回类型((U) -> V) -> ((T) -> U) -> (T) -> V
完全相同的值,并用三个类型参数替换为Double
。
这些括号仅用于解析歧义。 Kotlin允许使用以下形式之一的lambda调用函数:f({ })
,f() { }
,f { }
。如果删除括号,标记为(3)的lambda将被视为第一次调用的参数。解决这种歧义的一种方法是添加()
告诉编译器调用的是(1)的返回值,而不是higherCompose
因此,此lambda作为((U) -> V)
的参数传递给higherCompose
的结果类型,从而产生((T) -> U) -> (T) -> V
。
之所以添加这些括号是因为Kotlin不允许直接使用另一个lambda调用括号(f() { }
)之外的lambda的调用的返回值:禁止使用f() { } { }
,但添加另一个lambda之间的一对圆括号解决了这个问题:f() { }() { }
表示用lambda调用f
的结果。
此lambda作为((T) -> U)
参数传递给(3)的结果类型,并且此调用的结果为(T) -> V
如果通过括号内的所有lambda(f({ })
而不是f() { }
或f { }
形式),则可以得到该表达式的更少密码的版本:
higherCompose<Double, Double, Double>()({ x -> Math.sin(x) })({ x -> Math.PI / 2 - x })
请参阅:语言参考中的Lambda Expressions and Anonymous Functions。
答案 1 :(得分:0)
在Kotlin中处理功能组合的另一种方法是在功能类型上使用扩展功能。尝试这样的事情:
infix fun <P1, R1, R2> ((P1) -> R1).then(f: ((R1)-> R2)) : (P1) -> R2 {
return { p1 : P1 -> f(this(p1)) }
}
这允许您在代码中使用更简单的构造:
function1 then function1
使用上面的示例,您可以执行以下操作:
infix fun <P1, R1, R2> ((P1) -> R1).then(f: ((R1)-> R2)) : (P1) -> R2 {
return { p1 : P1 -> f(this(p1)) }
}
fun main() {
val c = { x: Double -> Math.sin(x)} then { x : Double -> Math.PI/2 - x }
println(c(2.4))
}
将显示0.8953331462437456
。
查看我的Functional FizzBuzz post使用这种方法。