Forced superclass in Swift Generics

I tried to implement a new method for combining two Array , returning Array , which contains a common data type for the other two.

To be clear, I would expect you to do something like (knowing that the syntax is incorrect ...):

 @infix func + <T,U,X where X super T, X super U>(left : Array<T>, right : Array<U>) -> Array<X>{ //join both arrays } 

Always thinking that the compiler is capable of detecting a common type of ancestor for both classes. If this is not possible, then what will be the right approach? Make this "super" type explicit?

+6
source share
2 answers

Swift type inference is smarter than you think. The secret is to look at the signature of the nil-coalescing operator ?? :

 func ??<T>(optional: T?, defaultValue: @autoclosure () -> T) -> T func ??<T>(optional: T?, defaultValue: @autoclosure () -> T?) -> T? 

Using this operator, it is clear that it will promote T as the closest common ancestor of any types passed to it, up to Any , for example:

 let i: Int? = 3 let s: String? = "3" let a: Any? = i ?? s 

This compiles and works, but the type of a is Any (which is actually a protocol). In some cases, you need to provide type proofs for the compiler, and in some cases you will not. If the types have a common ancestor that is not a protocol, then it seems that evidence is not needed. Can you think that ?? gets special treatment from the compiler, but it’s not. You can easily roll your own.

To come to your attempt, you have thus overdone it. (As I was when I had a similar problem.) You only need one type.

If we used the + function as a function, it would look like this:

 func joinArrays<T>(array1: [T], array2: [T]) -> [T] { return array1 + array2 } class Base {} class Derived1 : Base {} class Derived2 : Base {} let a1 = [Derived1(), Derived1()] let a2 = [Derived2(), Derived2()] let a = joinArrays(a1, a2) 

Type a - Array<Base> , since it is the closest common ancestor of type type parameters.

I used this "type advancement" to create all kinds of complex coalescing / monadic Γ  la Haskell operators. The only misunderstanding was that Swift does not support covariance of type type parameters.

+1
source

Syntax : can be used as follows:

 // The parameter must be a UIViewController, or subclass func changeViewColor<T: UIViewController>(vc: T) { vc.view.backgroundColor = UIColor.redColor() } 
0
source

Source: https://habr.com/ru/post/971097/


All Articles