Skip to content

Instantly share code, notes, and snippets.

@jemmons
Created January 20, 2019 00:54
Show Gist options
  • Save jemmons/cfe048d35fd6ca4c17a8a66625d4efcc to your computer and use it in GitHub Desktop.
Save jemmons/cfe048d35fd6ca4c17a8a66625d4efcc to your computer and use it in GitHub Desktop.
Currying higher-order functions results in broken types.
import Foundation
// Given what seems to be a pretty standard definition of `curry`…
public func curry<T, U, Z>(_ ƒ: @escaping (T, U) -> Z) -> (T) -> (U) -> Z {
return { a in
return { b in
ƒ(a, b)
}
}
}
// Currying non-function arguments works fine.
func lowerOrder(_ x: String, _ y: String) { }
curry(lowerOrder) is (String) -> (String) -> Void
//> true
// But currying a higher-order function leaves us with some unknowable, unmatchable type!
func higherOrder(_ x: String, _ y: (String) -> Int) { }
curry(higherOrder) is (String) -> ((String) -> Int) -> Void
//> false?!?!
// Even though it looks like the type ought to be correct.
print(type(of: curry(higherOrder)))
//> (String) -> ((String) -> Int) -> ()
// It only seems to be a problem when function types are in the params. Returning a function works fine.
func maker(_ x: String, _ y: String) -> (String)->Int { return { _ in 42 }}
curry(maker) is (String) -> (String) -> (String)->Int
//> true
// And just to be sure it's not a problem with any signature with this shape, this works fine.
func staticDef(_ x: String) -> ((String) -> Int) -> Void { return { _ in 42 }}
staticDef is (String) -> ((String) -> Int) -> Void
//> true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment