The point of the example setup I sent, is to provide a simple method for 
setting and/or getting values from dictionary-like types. For example, I can 
create a Bond between a dictionary type of [String: Any] and a value type of 
Foo (some class or struct). The code I sent omits some or the more primitive 
types in the implementation. There is another struct called Bond, and it relies 
on solely a single dictionary type. The point is to take a given dictionary and 
get or set a value. There are to be no explicitly stated generic constraints on 
the value type because the point is to convert values. 

I still think there are plenty of benefits to associated type and generic type 
inferencing. The use case I have is one where it would be really helpful, but 
the actual example I provided cannot be justification alone. There really 
should be some sort of method, at the very least, to disambiguate a generic 
type from that of a required typealias. The language would greatly benefit from 
such a feature.

>> On Jun 24, 2017, at 9:41 PM, Xiaodi Wu <[email protected]> wrote:
>> 
>> On Fri, Jun 23, 2017 at 8:29 PM, David Moore via swift-evolution 
>> <[email protected]> wrote:
>> 
>> protocol Bondable {
>>     associatedtype Key
>>     associatedtype Value
>>     
>>     static func new() -> Self
>>     
>>     func value(forKey key: Key) -> Value?
>>     
>>     mutating func updateValue(_ value: Value?, forKey key: Key)
>> }
>> 
>> extension Dictionary: Bondable {
>>     static func new() -> Dictionary<Key, Value> {
>>         return Dictionary<Key, Value>()
>>     }
>>     
>>     func value(forKey key: Key) -> Value? {
>>         return self[key]
>>     }
>>     
>>     mutating func updateValue(_ value: Value?, forKey key: Key) {
>>         self[key] = value
>>     }
>> }
>> 
>> struct Bridge<A, B> {
>>     struct Getter {
>>         var transform: ((B) -> A?)
>>     }
>>     
>>     struct Setter {
>>         var transform: ((A) -> B?)
>>     }
>>     
>>     var get: Getter
>>     var set: Setter
>> }
>> 
>> protocol Bonding {
>>     associatedtype Dictionary: Bondable
>>     associatedtype Value
>>     
>>     var key: Dictionary.Key { get set }
>>     
>>     var bridge: Bridge<Value, Dictionary.Value> { get set }
>>     
>>     func value(from aDictionary: Dictionary, using set: Bridge<Value, 
>> Dictionary.Value>.Getter) -> Value?
>>     
>>     func addValue(_ value: Value, to aDictionary: inout Dictionary, using 
>> get: Bridge<Value, Dictionary.Value>.Setter)
>> }
>> 
>> extension Bonding {
>>     
>>     func value(from aDictionary: Dictionary, using get: Bridge<Value, 
>> Dictionary.Value>.Getter) -> Value? {
>>         if let value = aDictionary.value(forKey: key) {
>>             return get.transform(value)
>>         } else {
>>             return nil
>>             
>>         }
>>     }
>>     
>>     func addValue(_ value: Value, to aDictionary: inout Dictionary, using 
>> set: Bridge<Value, Dictionary.Value>.Setter) {
>>         aDictionary.updateValue(set.transform(value), forKey: key)
>>     }
>> }
>> 
>> struct ComplexBond<__Dictionary: Bondable, __Value>: Bonding {
>>     typealias Dictionary = __Dictionary
>>     typealias Value = __Value
>>     
>>     var key: __Dictionary.Key
>>     
>>     var bridge: Bridge<__Value, __Dictionary.Value>
>> }
>> 
>> The above is an example implementation of the `Bonding` protocol, where the 
>> preexisting names of the associated types, `Dictionary` and `Value`, are 
>> already appropriately named. It would be great if I could just add a simple 
>> keyword prefixing the `typealias` keyword which would enable the inferencing 
>> behavior. 
> 
> You already don't need to use a typealias for `Value`. It can already be 
> inferred from the type of `bridge`.
> 
> ```
> struct ComplexBond<__Dictionary: Bondable, Value>: Bonding {
>   typealias Dictionary = __Dictionary
>   var key: Dictionary.Key
>   var bridge: Bridge<Value, Dictionary.Value>
> }
> 
> // This compiles.
> ```
> 
> The issue with `Dictionary` and `__Dictionary` is interesting, and here is my 
> analysis:
> 
> The thing is, you don't actually need `Dictionary` to be a typealias for 
> `__Dictionary` _in order for `ComplexBond` to conform to `Bonding`_ (though 
> you may require this for the semantics of `ComplexBond` itself). For 
> instance, I can instead declare a `ComplexBond2` as follows:
> 
> ```
> struct ComplexBond2<__Dictionary: Bondable, Value, __AnotherDictionary: 
> Bondable>: Bonding
> where __Dictionary.Key == __AnotherDictionary.Key, __Dictionary.Value == 
> __AnotherDictionary.Value {
>   typealias Dictionary = __AnotherDictionary
>   var key: __Dictionary.Key
>   var bridge: Bridge<Value, __Dictionary.Value>
> }
> ```
> 
> Put another way, for the purposes of conformance, it only matters that 
> `__Dictionary.Key` is the same type as `Dictionary.Key` and that 
> `__Dictionary.Value` is the same type as `Dictionary.Value`, but 
> `ComplexBond.__Dictionary` and `Bonding.Dictionary` are not required _by the 
> protocol_ to be the same type. Of course, if `ComplexBond` had to implement 
> some protocol requirement by which you could infer that `__Dictionary` must 
> be the same type as `Dictionary`, then that inference would be possible too 
> without a typealias.
> 
> Put another way, the fact that `typealias Dictionary = __Dictionary` is 
> required here is not merely a reflection of some shortcoming in the 
> expressiveness of the language: it reflects the fact that this relationship 
> cannot be inferred because the relationship doesn't have to be that way--as 
> far as conformance of `ComplexBond` to `Bonding` is concerned. Instead, with 
> that statement, you're making a _choice_ based on the desired semantics for 
> `ComplexBond`, a choice that is not forced upon you by the protocol to which 
> it conforms. In that sense, it is actually useful that Swift prevents you 
> from naming both `Dictionary` and `__Dictionary` the same thing: you are 
> reminded that the relationship between the two is a choice of the conforming 
> type, not an inevitability of protocol conformance; by contrast, if some 
> requirement *does* make the relationship an inevitability, such a typealias 
> is not required and you *can* name the two with the same name (as is the case 
> with `Value`).
> 
> 
>> 
>>> On Jun 23, 2017, 8:36 PM -0400, Xiaodi Wu <[email protected]>, wrote:
>>> Yes, examples will be helpful.
>>> 
>>> 
>>>> On Fri, Jun 23, 2017 at 19:28 David Moore via swift-evolution 
>>>> <[email protected]> wrote:
>>>> I do indeed have quite a few real examples of this, such prompted me to 
>>>> bring this up. I think this could be done without any impact to existing 
>>>> code, but it would require some type of keyword. Take the following as a 
>>>> possible prototype.
>>>> 
>>>> protocol Foo { 
>>>>     associatedtype T
>>>> }
>>>> 
>>>> struct Bar<T> : Foo {
>>>>     keyword typealias T // Or really any other syntactical implementation.
>>>> }
>>>> 
>>>> With an opt-in method we could implement this without affecting existing 
>>>> code, thereby making this more viable. I will send some examples later.
>>>> 
>>>> On Jun 23, 2017, at 6:52 PM, Xiaodi Wu <[email protected]> wrote:
>>>> 
>>>>> There could be source-breaking implications for such a feature, 
>>>>> especially with retroactive conformance. Therefore, I think this could be 
>>>>> very tricky and I'd want to be convinced that the benefits are very great 
>>>>> to risk such a disturbance. Here, I think the problem is rather mild, and 
>>>>> here's why:
>>>>> 
>>>>> It is true that, in your example specifically, renaming T to U is the 
>>>>> only solution (that I know of, anyway). However, for any "serious" 
>>>>> protocol P, there's likely to be a required property of type P.T, or a 
>>>>> function that takes an argument of type P.T or returns a value of type 
>>>>> P.T. Therefore, implementing that requirement in Bar with a corresponding 
>>>>> property/argument/return value of type Bar.T would generally do the trick.
>>>>> 
>>>>> Have you got any real-world examples where you're running into this issue?
>>>>> 
>>>>>> On Fri, Jun 23, 2017 at 17:03 David Moore via swift-evolution 
>>>>>> <[email protected]> wrote:
>>>>>> Hello Swift Evolution,
>>>>>> 
>>>>>> This may have already been discussed before, but I just came across a 
>>>>>> bothersome language aspect which reminded me to propose a solution. 
>>>>>> Currently, if we want to add generics to a protocol the only way to do 
>>>>>> so is with associated types. I am quite fine with the current approach 
>>>>>> with respect to those semantics.
>>>>>> 
>>>>>> There is, however, a weakness that is built in with using associated 
>>>>>> types. That weakness is the lack of associated type and generic 
>>>>>> inference. To be more clear about what I mean, take the following as an 
>>>>>> example.
>>>>>> 
>>>>>> protocol Foo {
>>>>>>     associatedtype T
>>>>>> }
>>>>>> 
>>>>>> The foregoing protocol is quite basic, but uses an associated type with 
>>>>>> the name “T.” Giving the associated type that name will illustrate the 
>>>>>> dilemma encountered later on down the pipeline.
>>>>>> 
>>>>>> struct Bar<T> : Foo {
>>>>>>     // What am I supposed to do? The name is used for both the generic 
>>>>>> and the type alias Foo needs for conformance.
>>>>>>     typealias T = T // Error!
>>>>>> }
>>>>>> 
>>>>>> The above illustrates a situation where we want to connect the generic, 
>>>>>> which is supposedly named appropriately, and the protocol’s associated 
>>>>>> type. There is no elegant solution for this at the moment. All I could 
>>>>>> do is the following.
>>>>>> 
>>>>>> struct Bar<U> : Foo {
>>>>>>     typealias T = U // Not nearly as readable.
>>>>>> }
>>>>>> 
>>>>>> Now, there may be a few ways to go about adding support for generic 
>>>>>> inference. The compiler as it is already does some awesome inference get 
>>>>>> when it comes to generics, so why not take it a step further? I propose 
>>>>>> the introduction of a keyword, or anything else that could work, to 
>>>>>> specify explicitly what a given type alias declaration would do when it 
>>>>>> comes to inferencing. Requiring a keyword would ensure source 
>>>>>> compatibility remains intact, and it would also make the code more 
>>>>>> readable.
>>>>>> 
>>>>>> I don’t know if this would be something that people could find useful, 
>>>>>> but I surely would. The implicit mapping of an associated type and a 
>>>>>> given generic by their names, would be a natural development.
>>>>>> 
>>>>>> Let me know if this is just useless, or if could be a potential feature.
>>>>>> 
>>>>>> Thank you,
>>>>>> David Moore
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> [email protected]
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected]
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to