Kotlin高阶函数组合

时间:2018-02-22 16:29:50

标签: kotlin

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

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

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

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

3 个答案:

答案 0 :(得分:1)

单向:

你必须将这两个Int作为compose的附加参数传递给你:

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

Lambdas是一个进一步的抽象层次,它为您提供了使行为变量的机会,您仍然需要为它们提供数据。

更抽象的方法:

你可以进一步抽象,让compose返回一个lambda,它结合了另外两个lambdas的结果(让我们称之为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之外完成。

更抽象的方法:

在您的撰写功能中,您可以使用简单的添加作为合成操作。您甚至可以通过传递第三个lambda ab来使该操作变量,该lambda a告诉您的函数如何撰写bfun compose3(a: (Int, Int) -> Int, b: (Int, Int) -> Int, ab: (Int, Int) -> Int) = { c: Int, d: Int -> ab(a(c, d), b(c, d)) }

rng <- range(time(dta))
g <- xts(, seq(rng[1], rng[2], by = 1))
na.locf(merge(dta, g))

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

答案 1 :(得分: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) }

那就是它。

答案 2 :(得分:0)

另一种值得的方法是使用中缀扩展功能。对于参数类型为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