Hi Anton and welcome back to the discussion. :)

While trying to find the talk about overlapping protocol members from different 
protocols I spotted your proposal: 
https://github.com/Anton3/swift-evolution/blob/generic-protocols/proposals/NNNN-generic-protocols.md

Just one hint, inside an extension or a type (non-protocol) we write typealias 
instead of associatedtype.

Here is the evolution-thread: 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon–20160919/027122.html

The suggestion there was to prefix everything with the corresponding protocol 
when there is a collision.

struct Test : Foo<Int>, Foo<String> {
    init(_ value: Foo<Int>.Value) { … }    // or better: init(_ value: Int)
    init(_ value: Foo<String>.Value) { … } // init(_ value: String)
     
    // assume both had the function `foo()`
    func Foo<Int>.foo() { … }
    func Foo<String>.foo() { … }
}
Is there really a need for true generic protocols? I’m still fascinated by the 
idea how a generic and constrained typealias could create this new ‘pseudo’ 
generic protocol.

protocol Foo {
  associatedtype Value
  init(_ value: Value)
  func foo()     
}

typealias GenericFoo<T> = Foo where Value == T

struct OtherTest : GenericFoo<Int>, GenericFoo<String> {
    init(_ value: Int) { … }
    init(_ value: String) { … }
     
    func GenericFoo<Int>.foo() { … }
    func GenericFoo<String>.foo() { … }
}
But allowing this kind of typealias probably means that one would in general 
allow the where clause on any protocol anywhere in the language. :/ Or I might 
be totally wrong at this point.

Again, one cool thing is that this would also define some best practice of how 
we could use existentials.

typealias + non-/generic type name + = protocol/class + optional N * (& + 
protocol) + optional where clause

That pattern is more reusable then the strict Any< … > would be.



-- 
Adrian Zubarev
Sent with Airmail

Am 9. Dezember 2016 um 20:16:14, Anton Zhilin (antonyzhi...@gmail.com) schrieb:

A fundamental problem is, how do we get rid of  
associatedtype duplicates?

A pedantic approach is to add trait operations for conformances:

protocol Constructible {
    associatedtype Value
    init(_ value: Value)
}

struct MyStruct {
    conformance Constructible {
        rename associatedtype ValueInt = Value
    }
    conformance Constructible {
        rename associatedtype ValueString = Value
    }

    typealias ValueInt = Int  // or can be inferred
    init(_ value: Int)

    typealias ValueString = String  // or can be inferred
    init(_ value: String)
}
This way, if there is a if there is a conflicting member, which does not use 
any of the associated types, like  
func foo(), then we can give it different meanings in different conformances.
Although this approach is the most clean one from theoreticall point of view, 
choosing different names for associated types would not look very good in 
practise.

One possible solution is to always automatically match  
associatedtypes, without using  
typealiases.

protocol ConstructibleFromBoth {
    associatedtype First
    associatedtype Second
    init(first: First)
    init(second: Second)
}

struct MyStruct : ConstructibleFromBoth {
    init(first: Int)
    init(second: Double)
}

extension MyStruct {
    init(first: String)   // now there are 2 distinct conformances
}

extension MyStruct {
    init(second: Float)   // now there are 4 distinct conformances
}
It introduces another potentially exponential algorithm for compiler. Although, 
does it? During a conformance test in some generic function, compiler will need 
to only find the first match or two.
Anyway, I guess, people would prefer to state explicitly that a type conforms 
to multiple versions of a protocol.

Attempt #3. We can resolve the conflict between associated types, if we delete 
(if trait sense) confliting associated types from the type. But with 
extensions, all associated types can be made conflicting. So there needs to be 
some attribute, marking, which of the associated types we don’t want. It can 
lie at the place of conformance:

struct MyStruct { }
extension MyStruct : @dontCreateTypealiases (Constructible where Value == Int) 
{ ... }
extension MyStruct : @dontCreateTypealiases (Constructible where Value == 
String) { ... }
// MyStruct.Value.self  // error, no such type

struct NormalConformanceTest : Constructible { init(_ value: Float) }
NormalConformanceTest.Value.self  //=> Float
Or we can let constrained protocols syntax carry this attribute by default:

extension MyStruct : (Constructible where Value == Int) { ... }
// MyStruct.Value.self  // error, no such type

struct NormalConformanceTest: Constructible { init(_ value: Float) }
NormalConformanceTest.Value.self  //=> Float
The only thing left to solve is generic protocol declaration syntax and 
protocol specialization syntax. I’d like to present two ways to do this. First, 
taking ideas from Rust:

protocol ContainsCollection<Element> {
    associatedtype CollectionType : Collection where CollectionType.Element == 
Element
    func collection() -> CollectionType
}

extension String : ContainsCollection<Character>, 
ContainsCollection<UnicodeScalar>, ContainsCollection<CChar> {
    func collection() -> CharacterView
    func collection() -> UnicodeScalarView
    func collection() -> ContiguousArray<CChar>
}
Generic parameters are used to disambiguate between different conformances, and 
associated types are just matched. Explicit  
typealias specifiction is prohibited, because conflicts.

Second, without modifying current protocol declaration syntax:

protocol ContainsCollection {
    associatedtype Element
    associatedtype CollectionType : Collection where CollectionType.Element == 
Element
    func collection() -> CollectionType
}

extension String : ContainsCollection<Element: Character>, 
ContainsCollection<Element: UnicodeScalar>, ContainsCollection<Element: CChar> {
    func collection() -> CharacterView
    func collection() -> UnicodeScalarView
    func collection() -> ContiguousArray<CChar>
}
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to