hamsternik
hamsternik

Reputation: 1426

Uncurrying curried Function in Swift

I have a function, which takes two arguments and returns a single value.

For example

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

Next step is to use a currying to get a function which takes the only first argument and return a closure with an appropriate signature. Also, I wrote a type alias to bring more clearness of the result type.

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) }
    }
}

But then I remembered about uncurry function which should return a default sum function signature if I'll apply it on the curryied result. So I tried to implement a variation of uncurry, and what I'll get at the result:

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)
    }
}

But here's a problem - I can't use this uncurry function with the result of currying on sum function, because uncurry requires only @escaping parameter where curryied function returns a non-escaping variation.

Here's a Swift compiler error:

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

Does anyone know are there any ways to create uncurry function in Swift which would be applicable to the curryied function result.

Upvotes: 1

Views: 246

Answers (2)

Alexander
Alexander

Reputation: 63167

Your uncurry function can do just that, uncurry curried functions:

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

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

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

The issue is that you're mistaking uncurrying for unapplying. Once you've partially or fully applied a curried function (or any function, for that matter), there's no mechanism to go back, to get the original function that produced the result.

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

Imagine if that were the case. Every integer, string, and other value would have to remember a history of what functions caused it. I can't think of a single use case for that. For one, it would require dynamic typing (or forced compile-time casting in a static language like Swift), because you can't predict the signature of an arbitrary function that produces a given result.

Upvotes: 2

hamsternik
hamsternik

Reputation: 1426

As @Alexander write above, I can easily use uncurry function for curried result of the sum().

I just made an error when passed a result value of the curried function.

Upvotes: 0

Related Questions