[swift-evolution] [Discussion] Generic protocols

Adrian Zubarev adrian.zubarev at devandartist.com
Tue Dec 6 10:14:29 CST 2016

I’m not in a rush. Right now I’m just bike shedding here and there. The problem with typealias I see is, that it really is a type alias and not a new type I’d want it to be. Or am I wrong here?

I’m curious what some of the core team would say on something like typealias GenericProto<T> = Proto where P == T.

Regarding existentials, yes that way it feels really redundant. To be honest, I see existentials like Any<Collection where …> as a constrained interface I’d want to use somewhere. But existentials are not protocols to which I could conform to right?!

The main problem existentials solve is when you loose some constrain on a class or when you want to combine different protocols together.

typealias MyConstrainedClassType = Any<BaseClassType, SomeProtocol where … >

typealias MyConstrainedExistential = Any<SomeProtocol, SomeOtherProtocol where … >
But what if I want to constrain a single protocol so that it creates a new protocol which is parameterized?

protocol Foo {
   associatedtype F
   func workWith(_ f: F)

// These are interfaces but not new protocols right?!
typealias ExistentialIntFoo = Any<Foo where F == Int>
typealias ExistentialFoo<T> = Any<Foo where F == T>  

// VS:
// These 'could' produce new protocols to which you could conform to  
// (like SE-0142) or one could use these as interfaces (redundant with existentials)
typealias IntFoo = Foo where F == Int
typealias GenericFoo<T> = Foo where F == T

// Multiple conformances would be allowed this way `GenericFoo<Int> != GenericFoo<String>`
protocol Proto : GenericFoo<Int>, GenericFoo<String> {}

// What about merging?
typealias MergedFoos = GenericFoo<String> & GenericFoo<Int>

// Would this be equivalent to something like:
protocol MergedFoos : /* correct base protocol??? */ {
    func workWith(_ f: Int)
    func workWith(_ f: String)
typealias could be so much powerful if you only imagine something like this:

protocol Boo {
   associatedtype B
   func execute(_ b: B)

typealias Combined1 = Any<Foo, Boo where F == Int, B == String>
typealias Combined2 = Foo & Boo where F == Int, B == String

// There was a discussion about using `&` instead of `,`
protocol New : Foo, Boo where F == Int, B == String {}

// vs:
protocol New : Combined2 {}

class Base {}
class A : Base, Boo { func execute(_ b: Int) }
class B : Base, Boo { func execute(_ b: String) }

typealias BaseAndBoo = Any<Base, Boo>
typealias BaseAndBoo = Base & Boo

let baseAndBoo: BaseAndBoo = A() // or B()

typealias BaseAndIntBoo = Any<Base, Boo where B == Int>
typealias BaseAndIntBoo = Base & Boo where B == Int

let baseAndIntBoo: BaseAndIntBoo = A()
I kinda like the latter, because it either creates a new protocol or a new class, to which you can conform or inherit from. Plus it’s less Any<> noise.

Adrian Zubarev
Sent with Airmail

Am 6. Dezember 2016 um 10:33:25, Anton Zhilin (antonyzhilin at gmail.com) schrieb:

What makes me worry is if this syntax is really the best one possible:

typealias ConstructibleFrom<V> = ConstructibleFromValue where ValueType == V
I find it strange that such exact line with  
typealias and  
where is required. I was hoping for an expression that lets us specialize a protocol and use it in-place, like so:

extension MyType : ConstructibleFromValue<ValueType == V>
extension MyType : (ConstructibleFromValue where ValueType == V)
Also I thought that this topic does not really belong to generalized existentials:

var x: ConstructibleFrom<Float>
I mean, we specify all the types here, so the compiler should just specialize the protocol and use it as a normal existential. The only thing that does not allow us to do that now is syntax.
By comparison, the following  
typealias does require generalized existentials, because some  
associatedtypes, including  
Iterator, are not specified:

typealias GenericCollection<E> = Collection where Iterator.Index == Int, Element == E
It also shows that future generalized-existentials syntax will likely be exactly the same as the one we choose now for protocol specialization.
So we still should think twice before proceeding. We can implement this proposal now, but do we want to?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161206/139b1e0c/attachment.html>

More information about the swift-evolution mailing list