Generic constraints with non-protocol types

It would be great if we could write generic constraints which are expressed in terms of other generic constraints. It would allow us to create much more powerful constructs with greater expressiveness to the type-system.


One example which would be helpful:

enum Either<T1,T2>
{
  case A( T1 )
  case B( T2 )

  func asCommonType<T where T1:T, T2:T>( type: T.Type ) -> T
  {
       switch self
       {
            case .A( let val ): return val as! T
            case .B( let val ): return val as! T
       }
  }
}


Then I could use the Either type like this:

let someView : Either<UIButton, UIImageView>
...
view.addSubview( someView.asCommonType( UIView.Type ) )


With compile-time guarantees which restrict the types that someView may be assigned, and also when it is used that it may be represented as a UIView. If anybody changes the code in a way which violates this relationship, it won't compile.


Currently this isn't possible, as the compiler complains on line 06 that "T" isn't a protocol type. I can't represent this type relationship statically to the Swift compiler.

What you're asking for might be useful, but I don't think your use case proves that.


This is the way I think the language should handle it:


protocol ViewMaster {}
extension UIButton: ViewMaster {}
extension UIImageView: ViewMaster {}

let someView: UIView: ViewMaster


Workaround until that:

class Class<ViewMasterView: UIView where ViewMasterView: ViewMaster> {
    let someView: ViewMasterView

Or just that:


protocol ViewMaster {}
extension UIView: ViewMaster {}
extension UIButton: ViewMaster {}
extension UIImageView: ViewMaster {}

let someView: ViewMaster = UIView() // or UIButton() // or UIImageView() ... etc...


Or ....

protocol ViewMaster {}
extension UIView:{
addSubview(view: ViewMaster ) { ... }
}
extension UIButton: ViewMaster {}
extension UIImageView: ViewMaster {}

etc....

That's really not a solution to anything, and the whole idea of adding junk dummy protocols around your project just to work around the type system is really abhorrent to me.


That dummy protocol is a guarantee of nothing. Anybody could add comformance to that protocol, and then totally defeat the type constraints I've built in to my components. I would need to flesh out that protocol with the specific methods I need (like removeFromSuperview), and I'd need to write shims for every method I need which accepts a concrete type and relies on inheritance for specialisation. Essentially, I would need to rewrite UIView as a protocol. And even then it would be horribly unsafe - somebody could just go ahead and write:


extension String : ViewMaster {}


and then they'd defeat all of your type guarantees and lose all of the information that those type constraints give.


In this case, you might know never to make String conform to ViewMaster. In other cases, you might not be aware of all of the implications of that "conformance" (especially if using 3rd-party libraries). You might conform to some abstractly-named protocol and find a bunch of APIs being enabled for you which you have no business dealing with with that data type.

I don't put any implementation detail because i think is not necessary.

But the idea is only the notion is better make some common protocol (with the necessary methods) or make a type constraints on a designated function. This constraint can be made in different ways of course...


Is the exactly same result of the "let someView: UIView: ViewMaster " line cited.

"junk dummy protocols" are actually known as "marker protocols". They won't be necessary when Swift allows us to extend existing type with attributes.


I don't know what you mean by this:

Anybody could add comformance to that protocol, and then totally defeat the type constraints I've built in to my components. I would need to flesh out that protocol with the specific methods I need (like removeFromSuperview), and I'd need to write shims for every method I need which accepts a concrete type and relies on inheritance for specialisation.


No programming language yet provides the amount of static analysis necessary for everyone's needs.

No programming language yet provides the amount of static analysis necessary for everyone's needs.

Guys, you should try C++ sometime ;)

Sure, C++ doesn't do everything, but but in Swift you can barelly do anything using generics.

I just had to put some fuel into this fire as I'm so frustrated by the lack of basic things in Swift.

Generic constraints with non-protocol types
 
 
Q