Fixing the type system

Yes, but:

//                            Are these two the same type or not?
//                                 .--'-.     .-'--.
func identity<T, U>(_ f: @escaping (T)->U) -> (T)->U {
    return f
}

func add(_ a: Int, _ b: Int) -> Int { return a + b }

print(type(of: add))           // Prints (Int, Int) -> Int
print(type(of: identity(add))) // Prints ((Int, Int)) -> Int

print(type(of: add) == type(of: identity(add))) // false

let f: (Int, Int) -> Int = add
var g = identity(f)
// g = add // ERROR: Cannot assign value of type
//        '(Int, Int) -> Int' to type '((Int, Int)) -> Int'

// Workaround:
g = { f($0.0, $0.1) }

// Have to call it with double parens like this:
let r = g((1, 2))
print(r) // Prints 3

It will work (same type, no double parentheses etc) if we use add1 instead of add though:

func add1(_ a: Int) -> Int { return a + 1 }

It looks like (T)->U and (T)->U in the definition of identity are the same type. But they are evidently not always the same.

So how do we write the identity function in Swift?

func identity<T>(_ f: T) -> T {
    return f
}

?

I know this is the identity function, but I mean one that takes only function types, and returns the same function type, no matter the number of parameters of that function type.

Maybe overload it for each number of parameters you want to support? No, that will result in Ambiguous use of 'identity'.

1 Like