A difference in perspective
Recently, Erica Sadun wrote about inconsistencies in Swift’s function-like constructs, such as KeyPath and method references—a post that appears lost in the apocalypse befalling her site.
Erica pointed out that method references return (A) -> () -> B functions that aren’t directly useable by higher order functions like map, which takes an (A) -> B function.
// Basic example
["a", "b"].map { "a".uppercased() } // ["A", "B"]
// Using a method reference. Hmm. Not quite what we wanted
["a", "b"].map(String.uppercased) // [() -> String, () -> String]
// Junky alternatives
["a", "b"].map(String.uppercased).map { $0() }
["a", "b"].map { String.uppercased($0)() }
She then works through a couple of solutions. A custom map style function on Sequence taking such a function and hiding the extra function application, and eventually an apply function that converts (A) -> () -> B to (A) -> B (and an accompanying operator).
One thing that struct me was how Erica derived all this from first principles, essentially reimplementing a function called flip, a common function in functional programming circles. From my perspective I immediately saw the problem as:
Oh, I need to flip this function and partially apply it to ()
Unfortunately, because we’re using Swift, it’s not quite that easy.
func flip<A, B, C>(f: (A) -> (B) -> C) -> (B) -> (A) -> C {
    return { b in { a in f(a)(b) } }
}
// Doesn't compile! For a couple of Swiftastic reasons.
["a", "b"].map(flip(String.uppercased)())
Swift treats () parameters as a special case, not just another type, so () can not be used as a B. Let’s write a special case version:
func flip<A, B>(_ f: @escaping (A) -> () -> B) -> () -> (A) -> B {
    return { { a in f(a)() } }
}
// This one does compile! Though you may notice it looks to have some redundancy.
["a", "b"].map(flip(String.uppercased)())
And we can now reimplement Erica’s apply in terms of our special case of flip:
func flap<A, B>(_ f: @escaping (A) -> () -> B) -> (A) -> B {
    return flip(f)()
}
["a", "b"].map(flap(String.uppercased))
Or just remove the intermediary special case of flip altogether, arriving at exactly Erica’s solution (operator not withstanding):
func flap<A, B>(_ f: @escaping (A) -> () -> B) -> (A) -> B {
    return { a in f(a)() }
}
["a", "b"].map(flap(String.uppercased))
In the end, we’ve arrived at the same solution to this specific problem. However, I hope I’ve illustrated how viewing programming from a slightly different perspective let us identify the issue quickly, and build a solution out of existing smaller, composeable pieces.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
