[Discussion] Easing the learning curve for introducing generic parameters

I strongly disagree with using some for generics. some in argument position and generics are dissimilar, but the syntax change will make them similar.

As discussed in the Structural opaque result types thread, (some P) -> (some P) would have following behavior.

// take opaque Numeric value and return opaque Numeric value.
let foo: (some Numeric) -> some Numeric = { (value: Double) in value * 2 }

let doubleValue = 4.2
foo(doubleValue)  // error (since some Numeric is opaque)
foo(4)            // OK (due to ExpressibleByIntegerLiteral conformance)
foo(.zero)        // OK (due to static member requirement)

However, if we adopt some for generics, the behaviors of closure and function get torn.

func foo(value: some Numeric) -> some Numeric { return value * 2 }
let doubleValue = 4.2
foo(doubleValue)  // OK (since value is generic)
foo(4)            // OK (since value is considered as Int)
foo(.zero)        // error (since there is no way to infer generic type parameter)

It would be really confusing for many developers. What is wrong here is using some for generics. some in the argument position should be also opaque in function.


If we want to add sugar, then we should use any for generics.

// two functions behave the same
func foo(value: any Numeric) -> some Numeric { return value * 2 }
func foo<T: Numeric>(value: T) -> some Numeric { return value * 2 }

Actually, Rust explained its impl as hybrid of generic any and reverse generic some in RFC 1951. I think this is logical direction.
As of existential types, we should search some other prefix like exist.

5 Likes