Swift中的curcurring函数

时间:2019-01-30 01:14:18

标签: ios swift functional-programming

我有一个函数,该函数带有两个参数并返回一个值。

例如

func sum(x: Int, y: Int) -> Int {
    return x + y
}

下一步是使用currying获取仅采用第一个参数的函数,并返回带有适当签名的闭包。 另外,我写了一个类型别名以使结果类型更清晰。

typealias EscapingClosure<A, B> = (A) -> B
func curry<A, B, C>(_ f: @escaping (A, B) -> C) -> EscapingClosure<A, (B) -> C> {
    return { (a: A) -> ((_ b: B) -> C) in
        return { (b: B) -> C in f(a, b) }
    }
}

但是后来我想起了uncurry函数,如果我将其应用于结果,它将返回默认的sum函数签名。 因此,我尝试实现uncurry的变体,以及得到的结果:

func uncarry<A, B, C>(_ f: @escaping EscapingClosure<A, (B) -> C>) -> (A, B) -> C {
    return { (a: A, b: B) -> C in
        return f(a)(b)
    }
}

但这是一个问题-我无法将此uncurry函数与sum函数一起使用,因为uncurry仅需要 @转义参数,其中curryied函数返回无转义的变体。

这是一个Swift编译器错误:

Cannot convert value of type '((A) -> Void) -> ()' to expected argument type '(_) -> (_) -> _'

有人知道有什么方法可以在Swift中创建uncurry函数,该方法适用于已获得的函数结果。

2 个答案:

答案 0 :(得分:1)

您的uncurry函数可以做到这一点,即无咖喱的咖喱函数:

let currableSum = curry(sum)
let uncurriedSum = uncurry(currableSum)

let add100 = currableSum(100)
print(add100(23)) // => 123

print(uncurriedSum(2, 2)) // => 4

问题是您误用了取消申请。一旦部分或完全应用了curried函数(或其他任何函数),便没有任何机制可以返回以获得产生结果的原始函数。

uncurry(add100) // ❌ can't "unapply" a partially applied function

想象一下是不是这种情况。每个整数,字符串和其他值都必须记住导致它的函数的历史记录。我无法想到一个用例。首先,这将需要动态类型化(或在诸如Swift之类的静态语言中进行强制编译时强制转换),因为您无法预测会产生给定结果的任意函数的签名。

答案 1 :(得分:0)

正如@Alexander所写,我可以轻松地使用uncurry函数获取sum()的查询结果。

当传递curried函数的结果值时,我只是犯了一个错误。