高阶函数组成表示法

时间:2019-05-27 20:55:01

标签: kotlin functional-programming

我正在使用此更高阶的撰写功能:

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} 

2 个答案:

答案 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              |
  1. 这是对higherCompose的初始无参数调用,该调用返回与higherCompose的返回类型((U) -> V) -> ((T) -> U) -> (T) -> V完全相同的值,并用三个类型参数替换为Double

  2. 这些括号仅用于解析歧义。 Kotlin允许使用以下形式之一的lambda调用函数:f({ })f() { }f { }。如果删除括号,标记为(3)的lambda将被视为第一次调用的参数。解决这种歧义的一种方法是添加()告诉编译器调用的是(1)的返回值,而不是higherCompose

  3. 因此,此lambda作为((U) -> V)的参数传递给higherCompose的结果类型,从而产生((T) -> U) -> (T) -> V

  4. 之所以添加这些括号是因为Kotlin不允许直接使用另一个lambda调用括号(f() { })之外的lambda的调用的返回值:禁止使用f() { } { },但添加另一个lambda之间的一对圆括号解决了这个问题:f() { }() { }表示用lambda调用f的结果。

  5. 此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使用这种方法。