首页 文章

Kotlin高阶函数组合

提问于
浏览
0

我试图弄清楚如何将一个函数声明地定义为Kotlin中另外两个函数的组合,但我正在努力 . 这是我的代码:

fun compose(a: (Int, Int) -> Int, b: (Int, Int) -> Int): Int {
    return a.invoke() + b.invoke()
}

compose函数的思想是它将接受两个函数作为它的输入(两个函数都需要两个Ints并返回一个Int)并返回两个传递函数的结果之和 . 问题是我必须调用传递的函数来计算它们的总和(显然是lol)但我不知道我希望在compose方法中调用的值(它们是传递给函数的值) .

我在这里完全遗漏了什么吗?我知道这可能是像Haskell这样的语言,Kotlin是否有可能?

3 回答

  • 0

    One way:

    您必须将两个Int作为附加参数传递给 compose ,如下所示:

    fun compose(c: Int, d: Int, 
                a: (Int, Int) -> Int, 
                b: (Int, Int) -> Int) = a(c, d) + b(c, d)
    

    Lambdas是一个进一步的抽象层次,它使您有机会使行为变量,您仍然必须为它们提供数据 .

    A more abstract approach:

    你可以进一步抽象,让 compose 返回一个lambda,它结合了另外两个lambda的结果(让我们称之为 compose2 ):

    // return type is inferred to (Int, Int) -> Int
    fun compose2(a: (Int, Int) -> Int, b: (Int, Int) -> Int) = { 
         c: Int, d: Int -> a(c, d) + b(c, d)
    }
    
    val f = compose2(/* pass lambdas */)
    

    f 是一个lambda本身,可以像这样调用:

    f(2, 4)
    

    所以, compose2 只会返回一个lambda,它会添加两个传递的lambdas的结果 . 实际调用在 compose2 之外完成 .

    An even more abstract approach:

    在您的撰写功能中,您可以使用简单的添加作为合成操作 . 你甚至可以通过传递第三个lambda ab 来使这个操作变量,它告诉你的函数如何编写 ab

    fun compose3(a: (Int, Int) -> Int, 
                 b: (Int, Int) -> Int, 
                 ab: (Int, Int) -> Int) = { 
        c: Int, d: Int -> ab(a(c, d), b(c, d))
    }
    

    结果又是一个lambda,它接受两个Ints并返回一个Int .

  • 1

    您需要一个新函数 (Int, Int) -> Int ,它是两个 (Int, Int) -> Int 函数的总和 .

    因此, compose(...) 返回的是另一个 (Int, Int) -> Int 类型的函数 .

    现在,我们有函数类型 compose . 它返回一个函数,而不是 Int 值 .

    fun compose(a: (Int, Int) -> Int, b: (Int, Int) -> Int): (Int, Int) -> Int
    

    它的身体怎么样?

    它将返回一个函数 . 让我们返回一个lambda表达式 { x: Int, y: Int -> a(x, y) + b(x, y) } .

    fun compose(a: (Int, Int) -> Int, b: (Int, Int) -> Int): (Int, Int) -> Int {
        return { x: Int, y: Int -> a(x, y) + b(x, y)}
    }
    

    现在我们可以省略所有不必要的部分 .

    fun compose(a: (Int, Int) -> Int, b: (Int, Int) -> Int): (Int, Int) -> Int =
        { x, y -> a(x, y) + b(x, y) }
    

    而已 .

  • 1

    另一个有 Value 的方法是使用 infix extension function . 对于参数类型为 Int 的情况,它可以是这样的:

    // Extension function on lambda
    private infix fun ((Int, Int) -> Int).plus(f: (Int, Int) -> Int) = {
        p1: Int, p2: Int, p3: Int, p4: Int -> this(p1, p2) + f(p3, p4)
    }
    
    // Usage
    val first: (Int, Int) -> Int = { a, b -> a + b }
    val second: (Int, Int) -> Int = { a, b -> a - b }
    
    // first two parameters (1 and 2) for the `first` lambda, 
    // second two parameters (4 and 3) for the `second` lambda
    val sum = (first plus second)(1, 2, 4, 3) // result is 4
    

相关问题