代码之家  ›  专栏  ›  技术社区  ›  Thomas Cook

Kotlin高阶函数合成

  •  5
  • Thomas Cook  · 技术社区  · 8 年前

    我试图找出如何将一个函数定义为Kotlin中其他两个函数的组合,但我很挣扎。这是我的代码:

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

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

    我是不是完全错过了什么?我知道这在Haskell这样的语言中是可能的,在Kotlin中是否可能?

    3 回复  |  直到 4 年前
        1
  •  4
  •   Willi Mentzel user670265    5 年前

    单向:

    必须将这两个整数作为附加参数传递给 compose 这样地:

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

    lambda是一个更高层次的抽象,它为您提供了使行为可变的机会,您仍然需要向它们提供数据。

    更抽象的方法:

    你可以进一步抽象,让 组成 返回一个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)
    

    所以 组件2 只返回一个lambda,该lambda将两个传递的lambda的结果相加。实际调用是在 组件2 .

    更抽象的方法:

    在compose函数中,使用简单的加法作为合成操作。您甚至可以通过传递第三个lambda使此操作变为变量 ab 它告诉函数如何组合 a b :

    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,它接受两个Int并返回一个Int。

        2
  •  4
  •   Naetmul    8 年前

    您需要一个新函数 (Int, Int) -> Int ,这是两个的和 (Int,Int)->内景 功能。

    因此,什么 compose(...) 退货是另一个 (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) }
    

    就是这样。

        3
  •  1
  •   Sergio    7 年前

    另一个有价值的方法是使用 中缀扩展函数 . 针对您的情况,参数类型为 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
    
    推荐文章