Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-07-02 Thread Thorsten Seitz via swift-evolution


> Am 25.06.2016 um 22:03 schrieb L. Mihalkovic :
> 
> 
> 
> Regards
> (From mobile)
> 
>> On Jun 25, 2016, at 8:48 PM, Thorsten Seitz  wrote:
>> 
>> 
>>> Am 25.06.2016 um 19:09 schrieb L. Mihalkovic :
>>> 
>>> 
>>> 
>>> Regards
>>> (From mobile)
>>> 
 On Jun 25, 2016, at 6:34 PM, Thorsten Seitz via swift-evolution 
  wrote:
 
 Sorry for the late reply — I had hoped to be able to think more deeply 
 about various points, 
 but I’m going to delay that instead of delaying the reply even more :-)
 
 
> Am 17.06.2016 um 19:04 schrieb Dave Abrahams :
> 
> 
> on Thu Jun 16 2016, Thorsten Seitz  wrote:
> 
>>> Am 13.06.2016 um 04:04 schrieb Dave Abrahams :
>>> 
>>> 
>>> on Fri Jun 10 2016, Thorsten Seitz  wrote:
>>> 
>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>> :
>> 
>> 
>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>> :
 
>> 
>> on Wed Jun 08 2016, Jordan Rose  wrote:
>> 
 On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
  wrote:
 
 
 on Wed Jun 08 2016, Thorsten Seitz
>>> 
 >
 wrote:
 
> Ah, thanks, I forgot!  I still consider this a bug, though (will 
> have
> to read up again what the reasons are for that behavior).
 
 Yes, but in the case of the issue we're discussing, the choices 
 are:
 
 1. Omit from the existential's API any protocol requirements that 
 depend
 on Self or associated types, in which case it *can't* conform to
 itself because it doesn't fulfill the requirements.
 
 2. Erase type relationships and trap at runtime when they don't 
 line up.
 
 Matthew has been arguing against #2, but you can't “fix the bug” 
 without
 it.
>>> 
>>> #1 has been my preference for a while as well, at least as a 
>>> starting
>>> point.
>> 
>> I should point out that with the resyntaxing of existentials to
>> Any, the idea that Collection's existential doesn't
>> conform to Collection becomes far less absurd than it was, so maybe 
>> this
>> is not so bad.
> 
> I think the problem is more that Any does not conform to
> a specific value for a type parameter T: Collection
> 
> What I mean by this is that `Collection` denotes a type family, a
> generic parameter `T: Collection` denotes a specific (though
> unknown) member of that type family and `Any` denotes
> the type family again, so there is really no point in writing
> Any IMO.
> The type family cannot conform to T because T is just one fixed 
> member of it.
> It conforms to itself, though, as I can write
> let c1: Any = …
> let c2: Any = c1
> 
> That’s why I think that we could just drop Any and simply 
> write Collection.
 
 Let me expand that a bit:
 
 Actually all this talk about existentials vs. generics or protocols
 vs. classes has had me confused somewhat and I think there are still
 some misconceptions present on this list sometimes, so I’ll try to
 clear them up:
>>> 
>>> There are several objectively incorrect statements here, and several
>>> others with which I disagree.  I was hoping someone else would write
>>> this for me, but since the post has such a tone of authority I feel I
>>> must respond.
>> 
>> You are right, the tone of my post was not appropriate, for which I
>> want to apologize sincerely.
> 
> My fundamental disagreement is with the content, not the tone.
> 
>> I still believe my statements to be valid, though, and will respond to
>> your arguments inline. Please don't get me wrong, I'm not trying to
>> have an argument for the argument's sake. All I want is to contribute
>> maybe a tiny bit to make Swift even better than it already is, by
>> sharing ideas and thoughts not only from me but from the designs of
>> other perhaps more obscure programming languages which I happen to
>> have stumbled upon in the past (often with much delight).
> 
> And I want you to know, even though I disagree with what you've written,
> that I very much 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-25 Thread L. Mihalkovic via swift-evolution


Regards
(From mobile)

> On Jun 25, 2016, at 8:48 PM, Thorsten Seitz  wrote:
> 
> 
>> Am 25.06.2016 um 19:09 schrieb L. Mihalkovic :
>> 
>> 
>> 
>> Regards
>> (From mobile)
>> 
>>> On Jun 25, 2016, at 6:34 PM, Thorsten Seitz via swift-evolution 
>>>  wrote:
>>> 
>>> Sorry for the late reply — I had hoped to be able to think more deeply 
>>> about various points, 
>>> but I’m going to delay that instead of delaying the reply even more :-)
>>> 
>>> 
 Am 17.06.2016 um 19:04 schrieb Dave Abrahams :
 
 
 on Thu Jun 16 2016, Thorsten Seitz  wrote:
 
>> Am 13.06.2016 um 04:04 schrieb Dave Abrahams :
>> 
>> 
>> on Fri Jun 10 2016, Thorsten Seitz  wrote:
>> 
> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
> :
> 
> 
> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
> :
>>> 
> 
> on Wed Jun 08 2016, Jordan Rose  wrote:
> 
>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>  wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Thorsten Seitz
>> 
>>> >> >
>>> wrote:
>>> 
 Ah, thanks, I forgot!  I still consider this a bug, though (will 
 have
 to read up again what the reasons are for that behavior).
>>> 
>>> Yes, but in the case of the issue we're discussing, the choices are:
>>> 
>>> 1. Omit from the existential's API any protocol requirements that 
>>> depend
>>> on Self or associated types, in which case it *can't* conform to
>>> itself because it doesn't fulfill the requirements.
>>> 
>>> 2. Erase type relationships and trap at runtime when they don't 
>>> line up.
>>> 
>>> Matthew has been arguing against #2, but you can't “fix the bug” 
>>> without
>>> it.
>> 
>> #1 has been my preference for a while as well, at least as a starting
>> point.
> 
> I should point out that with the resyntaxing of existentials to
> Any, the idea that Collection's existential doesn't
> conform to Collection becomes far less absurd than it was, so maybe 
> this
> is not so bad.
 
 I think the problem is more that Any does not conform to
 a specific value for a type parameter T: Collection
 
 What I mean by this is that `Collection` denotes a type family, a
 generic parameter `T: Collection` denotes a specific (though
 unknown) member of that type family and `Any` denotes
 the type family again, so there is really no point in writing
 Any IMO.
 The type family cannot conform to T because T is just one fixed member 
 of it.
 It conforms to itself, though, as I can write
 let c1: Any = …
 let c2: Any = c1
 
 That’s why I think that we could just drop Any and simply 
 write Collection.
>>> 
>>> Let me expand that a bit:
>>> 
>>> Actually all this talk about existentials vs. generics or protocols
>>> vs. classes has had me confused somewhat and I think there are still
>>> some misconceptions present on this list sometimes, so I’ll try to
>>> clear them up:
>> 
>> There are several objectively incorrect statements here, and several
>> others with which I disagree.  I was hoping someone else would write
>> this for me, but since the post has such a tone of authority I feel I
>> must respond.
> 
> You are right, the tone of my post was not appropriate, for which I
> want to apologize sincerely.
 
 My fundamental disagreement is with the content, not the tone.
 
> I still believe my statements to be valid, though, and will respond to
> your arguments inline. Please don't get me wrong, I'm not trying to
> have an argument for the argument's sake. All I want is to contribute
> maybe a tiny bit to make Swift even better than it already is, by
> sharing ideas and thoughts not only from me but from the designs of
> other perhaps more obscure programming languages which I happen to
> have stumbled upon in the past (often with much delight).
 
 And I want you to know, even though I disagree with what you've written,
 that I very much appreciate the contribution you're making.
>>> 
>>> Thanks! I’m very glad about that!
>>> 
>>> 
 
>>> (1) misconception: protocols with associated types are somehow very
>>> different from generics
>>> 
>>> I don’t think 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-25 Thread Thorsten Seitz via swift-evolution

> Am 25.06.2016 um 19:09 schrieb L. Mihalkovic :
> 
> 
> 
> Regards
> (From mobile)
> 
> On Jun 25, 2016, at 6:34 PM, Thorsten Seitz via swift-evolution 
> > wrote:
> 
>> Sorry for the late reply — I had hoped to be able to think more deeply about 
>> various points, 
>> but I’m going to delay that instead of delaying the reply even more :-)
>> 
>> 
>>> Am 17.06.2016 um 19:04 schrieb Dave Abrahams >> >:
>>> 
>>> 
>>> on Thu Jun 16 2016, Thorsten Seitz >> > wrote:
>>> 
> Am 13.06.2016 um 04:04 schrieb Dave Abrahams  >:
> 
> 
> on Fri Jun 10 2016, Thorsten Seitz  > wrote:
> 
>>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>>> >:
>>> 
>>> 
 Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
 >:
>> 
 
 on Wed Jun 08 2016, Jordan Rose > wrote:
 
>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>> > wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz
> 
>> 
>> > >>
>> wrote:
>> 
>>> Ah, thanks, I forgot!  I still consider this a bug, though (will 
>>> have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices are:
>> 
>> 1. Omit from the existential's API any protocol requirements that 
>> depend
>> on Self or associated types, in which case it *can't* conform to
>> itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't line 
>> up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” 
>> without
>> it.
> 
> #1 has been my preference for a while as well, at least as a starting
> point.
 
 I should point out that with the resyntaxing of existentials to
 Any, the idea that Collection's existential doesn't
 conform to Collection becomes far less absurd than it was, so maybe 
 this
 is not so bad.
>>> 
>>> I think the problem is more that Any does not conform to
>>> a specific value for a type parameter T: Collection
>>> 
>>> What I mean by this is that `Collection` denotes a type family, a
>>> generic parameter `T: Collection` denotes a specific (though
>>> unknown) member of that type family and `Any` denotes
>>> the type family again, so there is really no point in writing
>>> Any IMO.
>>> The type family cannot conform to T because T is just one fixed member 
>>> of it.
>>> It conforms to itself, though, as I can write
>>> let c1: Any = …
>>> let c2: Any = c1
>>> 
>>> That’s why I think that we could just drop Any and simply 
>>> write Collection.
>> 
>> Let me expand that a bit:
>> 
>> Actually all this talk about existentials vs. generics or protocols
>> vs. classes has had me confused somewhat and I think there are still
>> some misconceptions present on this list sometimes, so I’ll try to
>> clear them up:
> 
> There are several objectively incorrect statements here, and several
> others with which I disagree.  I was hoping someone else would write
> this for me, but since the post has such a tone of authority I feel I
> must respond.
 
 You are right, the tone of my post was not appropriate, for which I
 want to apologize sincerely.
>>> 
>>> My fundamental disagreement is with the content, not the tone.
>>> 
 I still believe my statements to be valid, though, and will respond to
 your arguments inline. Please don't get me wrong, I'm not trying to
 have an argument for the argument's sake. All I want is to contribute
 maybe a tiny bit to make Swift even better than it already is, by
 sharing ideas and thoughts not only from me but from the designs of
 other perhaps more obscure programming languages which I happen to
 have stumbled upon in the past (often with much delight).
>>> 
>>> And I want you to know, even though I disagree with what you've written,
>>> that I very much appreciate the contribution you're making.
>> 
>> Thanks! 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-25 Thread L. Mihalkovic via swift-evolution


Regards
(From mobile)

> On Jun 25, 2016, at 6:34 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> Sorry for the late reply — I had hoped to be able to think more deeply about 
> various points, 
> but I’m going to delay that instead of delaying the reply even more :-)
> 
> 
>> Am 17.06.2016 um 19:04 schrieb Dave Abrahams :
>> 
>> 
>> on Thu Jun 16 2016, Thorsten Seitz  wrote:
>> 
 Am 13.06.2016 um 04:04 schrieb Dave Abrahams :
 
 
 on Fri Jun 10 2016, Thorsten Seitz  wrote:
 
>>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>>> :
>>> 
>>> 
>>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>>> :
> 
>>> 
>>> on Wed Jun 08 2016, Jordan Rose  wrote:
>>> 
> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>  wrote:
> 
> 
> on Wed Jun 08 2016, Thorsten Seitz
 
>  >
> wrote:
> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices are:
> 
> 1. Omit from the existential's API any protocol requirements that 
> depend
> on Self or associated types, in which case it *can't* conform to
> itself because it doesn't fulfill the requirements.
> 
> 2. Erase type relationships and trap at runtime when they don't line 
> up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” 
> without
> it.
 
 #1 has been my preference for a while as well, at least as a starting
 point.
>>> 
>>> I should point out that with the resyntaxing of existentials to
>>> Any, the idea that Collection's existential doesn't
>>> conform to Collection becomes far less absurd than it was, so maybe this
>>> is not so bad.
>> 
>> I think the problem is more that Any does not conform to
>> a specific value for a type parameter T: Collection
>> 
>> What I mean by this is that `Collection` denotes a type family, a
>> generic parameter `T: Collection` denotes a specific (though
>> unknown) member of that type family and `Any` denotes
>> the type family again, so there is really no point in writing
>> Any IMO.
>> The type family cannot conform to T because T is just one fixed member 
>> of it.
>> It conforms to itself, though, as I can write
>> let c1: Any = …
>> let c2: Any = c1
>> 
>> That’s why I think that we could just drop Any and simply 
>> write Collection.
> 
> Let me expand that a bit:
> 
> Actually all this talk about existentials vs. generics or protocols
> vs. classes has had me confused somewhat and I think there are still
> some misconceptions present on this list sometimes, so I’ll try to
> clear them up:
 
 There are several objectively incorrect statements here, and several
 others with which I disagree.  I was hoping someone else would write
 this for me, but since the post has such a tone of authority I feel I
 must respond.
>>> 
>>> You are right, the tone of my post was not appropriate, for which I
>>> want to apologize sincerely.
>> 
>> My fundamental disagreement is with the content, not the tone.
>> 
>>> I still believe my statements to be valid, though, and will respond to
>>> your arguments inline. Please don't get me wrong, I'm not trying to
>>> have an argument for the argument's sake. All I want is to contribute
>>> maybe a tiny bit to make Swift even better than it already is, by
>>> sharing ideas and thoughts not only from me but from the designs of
>>> other perhaps more obscure programming languages which I happen to
>>> have stumbled upon in the past (often with much delight).
>> 
>> And I want you to know, even though I disagree with what you've written,
>> that I very much appreciate the contribution you're making.
> 
> Thanks! I’m very glad about that!
> 
> 
>> 
> (1) misconception: protocols with associated types are somehow very
> different from generics
> 
> I don’t think they are and I will explain why. The only difference is
> the way the type parameters are bound: generics use explicit parameter
> lists whereas protocols use inheritance. That has some advantages
> (think long parameter lists of generics) and some disadvantages.
> These ways are dual in a notation sense: generic types have to have
> all parameters bound whereas protocols cannot bind any of them.
> The „existential“ notation `Any<>` 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-25 Thread Thorsten Seitz via swift-evolution
Sorry for the late reply — I had hoped to be able to think more deeply about 
various points, 
but I’m going to delay that instead of delaying the reply even more :-)


> Am 17.06.2016 um 19:04 schrieb Dave Abrahams :
> 
> 
> on Thu Jun 16 2016, Thorsten Seitz  wrote:
> 
>>> Am 13.06.2016 um 04:04 schrieb Dave Abrahams :
>>> 
>>> 
>>> on Fri Jun 10 2016, Thorsten Seitz  wrote:
>>> 
> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
> :
> 
> 
>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>> :
 
>> 
>> on Wed Jun 08 2016, Jordan Rose  wrote:
>> 
 On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
  wrote:
 
 
 on Wed Jun 08 2016, Thorsten Seitz
>>> 
 >
 wrote:
 
> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> to read up again what the reasons are for that behavior).
 
 Yes, but in the case of the issue we're discussing, the choices are:
 
 1. Omit from the existential's API any protocol requirements that 
 depend
 on Self or associated types, in which case it *can't* conform to
 itself because it doesn't fulfill the requirements.
 
 2. Erase type relationships and trap at runtime when they don't line 
 up.
 
 Matthew has been arguing against #2, but you can't “fix the bug” 
 without
 it.
>>> 
>>> #1 has been my preference for a while as well, at least as a starting
>>> point.
>> 
>> I should point out that with the resyntaxing of existentials to
>> Any, the idea that Collection's existential doesn't
>> conform to Collection becomes far less absurd than it was, so maybe this
>> is not so bad.
> 
> I think the problem is more that Any does not conform to
> a specific value for a type parameter T: Collection
> 
> What I mean by this is that `Collection` denotes a type family, a
> generic parameter `T: Collection` denotes a specific (though
> unknown) member of that type family and `Any` denotes
> the type family again, so there is really no point in writing
> Any IMO.
> The type family cannot conform to T because T is just one fixed member of 
> it.
> It conforms to itself, though, as I can write
> let c1: Any = …
> let c2: Any = c1
> 
> That’s why I think that we could just drop Any and simply 
> write Collection.
 
 Let me expand that a bit:
 
 Actually all this talk about existentials vs. generics or protocols
 vs. classes has had me confused somewhat and I think there are still
 some misconceptions present on this list sometimes, so I’ll try to
 clear them up:
>>> 
>>> There are several objectively incorrect statements here, and several
>>> others with which I disagree.  I was hoping someone else would write
>>> this for me, but since the post has such a tone of authority I feel I
>>> must respond.
>> 
>> You are right, the tone of my post was not appropriate, for which I
>> want to apologize sincerely.
> 
> My fundamental disagreement is with the content, not the tone.
> 
>> I still believe my statements to be valid, though, and will respond to
>> your arguments inline. Please don't get me wrong, I'm not trying to
>> have an argument for the argument's sake. All I want is to contribute
>> maybe a tiny bit to make Swift even better than it already is, by
>> sharing ideas and thoughts not only from me but from the designs of
>> other perhaps more obscure programming languages which I happen to
>> have stumbled upon in the past (often with much delight).
> 
> And I want you to know, even though I disagree with what you've written,
> that I very much appreciate the contribution you're making.

Thanks! I’m very glad about that!


> 
 (1) misconception: protocols with associated types are somehow very
 different from generics
 
 I don’t think they are and I will explain why. The only difference is
 the way the type parameters are bound: generics use explicit parameter
 lists whereas protocols use inheritance. That has some advantages
 (think long parameter lists of generics) and some disadvantages.
 These ways are dual in a notation sense: generic types have to have
 all parameters bound whereas protocols cannot bind any of them.
 The „existential“ notation `Any<>` being discussed on this list is
 nothing more than adding the ability to protocols to bind the
 parameters to be used just like Java’s wildcards are adding the
 opposite feature to generics, namely not having to bind all
 parameters.
>>> 
>>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-22 Thread Jonathan Hull via swift-evolution

> On Jun 12, 2016, at 8:31 PM, Dave Abrahams  wrote:
> 
> 
> on Sat Jun 11 2016, Jonathan Hull  wrote:
> 
>>> If your code has many manual type erasing wrappers corresponding to
>>> protocols with associated types and/or Self requirements that also never
>>> have to trap type mismatches, that would certainly be instructive
>>> empirical data.  Would you care to share the protocols and wrappers you
>>> are talking about?
>> This code is a bit embarrassing (I wrote most of it as I was still
>> learning Swift), but if it is helpful I will share:
>> https://gist.github.com/jonhull/639e756ad5228348f93f40f06169588c
>> 
>> It doesn’t trap anywhere (that I know about). Some of the code which
>> calls it does throw an error in the case of mismatched types (but it
>> doesn’t/shouldn't crash).  
> 
> If that error is being thrown to handle what you consider to be a
> programming error, that is the moral equivalent of a trap.

Agreed.  In this case the error is thrown when two different user inputs don’t 
match types, and it results in a user facing error.  It basically functions as 
input validation.

It seems to me that Swift has four ways of handling failure:
1) Disallow it entirely
2) Trap (marked with !)
3) Throw (marked with try)
4) Return nil (marked with ?)

It seems to me that the Swift-y™ way to handle this is to disallow it until the 
programmer chooses the most appropriate of the other three options.

It may be that trapping is the right thing to do the majority of the time, but 
I definitely have use-cases where returning nil is the correct option.   


>> Most functions which use it are generic on the associatedType.
>> 
>> It does work fairly well though (even on the AppleWatch).  The main
>> issue is that I have no way to persist the values which have been
>> drawn into the type-erased world (or even the value-type world,
>> really).
>> 
>> Also, if anyone has a better way to write the type erasing wrapper, I
>> would love to hear it. These are very memory intensive…
> 
> It looks like you could make some gains by, instead of storing a closure
> for each operation, using a base class with a method for each operation,
> per the box types in
> https://github.com/apple/swift/blob/master/stdlib/public/core/ExistentialCollection.swift.gyb

Thank you, much appreciated.


> 
> HTH,
> -- 
> Dave
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-19 Thread L Mihalkovic via swift-evolution

> On Jun 19, 2016, at 8:35 AM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> 
> 
> Sent from my iPhone
> 
> On Jun 18, 2016, at 2:29 AM, Thorsten Seitz  > wrote:
> 
>> 
>>> Am 17.06.2016 um 16:11 schrieb Douglas Gregor >> >:
>>> 
>>> 
 On Jun 16, 2016, at 9:46 AM, Thorsten Seitz via swift-evolution 
 > wrote:
 
> 
> Am 16.06.2016 um 17:36 schrieb Paul Cantrell  >:
> 
>> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>> Protocols are a mechanism for deriving types from each other whereas 
>> generics are a way to parameterize types. My point was that Swift's 
>> other way to parameterize types, namely by associated types, is very 
>> similar to generics with wildcards when looking a the existentials of 
>> such protocols.
> 
> This has been a point of confusion for me as well. I keep hearing that 
> associated types are different from generic protocols, but this seems 
> like a distinction without a difference.
> 
> Suppose Swift allowed generic protocols. How would a hypothetical 
> Collection be different in practice from the proposed existential 
> Any?
> 
> Yes, in the realm of type theory and compiler internals they might 
> represented differently, sure. But in practice, in terms of what code can 
> actually do? I know of only two differences:
> 
> 1. A type can only conform to any given protocol with one set of type 
> parameters. (Nothing can be both Collection and Collection.)
> 
> 2. When a type conforms to Collection, it declares “associatedtype Foo” 
> instead of “: Collection”, and Foo can be inferred by the compiler 
> in some circumstances. That’s handy, but it’s a syntactic difference.
 
 That syntactic difference is *very* handy IMO for the following reason: 
 with generics I have to repeat all types over and over again which gets 
 ugly when I have levels of nesting where type parameters are constrained 
 by other generics, which requires adding their parameters to the parameter 
 list. Essentially the nested parameters have to be fully flattened because 
 each type parameter has to be explicitly specified.
 
 I’ll try to show that with a simplified example:
 
 // with associated types
 
 protocol Edge {
 associatedtype VertexType
 
 var source: VertexType { get }
 var target: VertexType { get }
 }
 
 protocol Graph {
 associatedtype EdgeType : Edge
 
 var vertices: [EdgeType.VertexType] { get }
 var edges: [EdgeType] { get }
 
 func outEdges(vertex: EdgeType.VertexType) -> [EdgeType]
 }
 
 protocol GraphIterator {
 associatedtype GraphType : Graph
 
 var graph: GraphType { get }
 
 var startVertex: GraphType.VertexType { get }
 
 func enter(vertex: GraphType.VertexType)
 func propagate(along edge: GraphType.EdgeType)
 func finish(vertex: GraphType.VertexType)
 }
 
 
 // with generics
 
 class Edge {
 var source: VertexType
 var target: VertexType
 }
 
 class Graph {
 
 var vertices: [VertexType]
 var edges: [EdgeType]
 
 func outEdges(vertex: VertexType) -> [EdgeType]
 
 }
 
 class GraphIterator> {
 
 var graph: GraphType
 
 var startVertex: VertexType
 
 func enter(vertex: VertexType)
 func propagate(along edge: EdgeType)
 func finish(vertex: VertexType)
 }
 
 Note, how the parameter list for GraphIterator exploded, because I had to 
 list each level of nested types down to the VertexType, whereas
 in the associated types example the GraphIterator simply declares an 
 associated type conforming to the topmost type of my nesting, the Graph.
 
 
> 
> Is there a deeper difference I’m missing?
 
 Maybe Dave can chime in here?
>>> 
>>> You can recover an associated type (say, X.Element) by just having the type 
>>> “X”, but this is not true for a type parameter. That doesn’t matter when 
>>> you have (or want to specify) that type… for example, your comment that 
>>> Collection and Any would basically 
>>> be the same thing.
>>> 
>>> However, with generalized/enhanced existentials you would be able to write
>>> 
>>> var heterogeneousArrayOfCollections: [Collection]
>>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-19 Thread Douglas Gregor via swift-evolution


Sent from my iPhone

> On Jun 18, 2016, at 2:29 AM, Thorsten Seitz  wrote:
> 
> 
>>> Am 17.06.2016 um 16:11 schrieb Douglas Gregor :
>>> 
>>> 
 On Jun 16, 2016, at 9:46 AM, Thorsten Seitz via swift-evolution 
  wrote:
 
 
> Am 16.06.2016 um 17:36 schrieb Paul Cantrell :
> 
> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> Protocols are a mechanism for deriving types from each other whereas 
> generics are a way to parameterize types. My point was that Swift's other 
> way to parameterize types, namely by associated types, is very similar to 
> generics with wildcards when looking a the existentials of such protocols.
 
 This has been a point of confusion for me as well. I keep hearing that 
 associated types are different from generic protocols, but this seems like 
 a distinction without a difference.
 
 Suppose Swift allowed generic protocols. How would a hypothetical 
 Collection be different in practice from the proposed existential 
 Any?
 
 Yes, in the realm of type theory and compiler internals they might 
 represented differently, sure. But in practice, in terms of what code can 
 actually do? I know of only two differences:
 
 1. A type can only conform to any given protocol with one set of type 
 parameters. (Nothing can be both Collection and Collection.)
 
 2. When a type conforms to Collection, it declares “associatedtype Foo” 
 instead of “: Collection”, and Foo can be inferred by the compiler in 
 some circumstances. That’s handy, but it’s a syntactic difference.
>>> 
>>> That syntactic difference is *very* handy IMO for the following reason: 
>>> with generics I have to repeat all types over and over again which gets 
>>> ugly when I have levels of nesting where type parameters are constrained by 
>>> other generics, which requires adding their parameters to the parameter 
>>> list. Essentially the nested parameters have to be fully flattened because 
>>> each type parameter has to be explicitly specified.
>>> 
>>> I’ll try to show that with a simplified example:
>>> 
>>> // with associated types
>>> 
>>> protocol Edge {
>>> associatedtype VertexType
>>> 
>>> var source: VertexType { get }
>>> var target: VertexType { get }
>>> }
>>> 
>>> protocol Graph {
>>> associatedtype EdgeType : Edge
>>> 
>>> var vertices: [EdgeType.VertexType] { get }
>>> var edges: [EdgeType] { get }
>>> 
>>> func outEdges(vertex: EdgeType.VertexType) -> [EdgeType]
>>> }
>>> 
>>> protocol GraphIterator {
>>> associatedtype GraphType : Graph
>>> 
>>> var graph: GraphType { get }
>>> 
>>> var startVertex: GraphType.VertexType { get }
>>> 
>>> func enter(vertex: GraphType.VertexType)
>>> func propagate(along edge: GraphType.EdgeType)
>>> func finish(vertex: GraphType.VertexType)
>>> }
>>> 
>>> 
>>> // with generics
>>> 
>>> class Edge {
>>> var source: VertexType
>>> var target: VertexType
>>> }
>>> 
>>> class Graph {
>>> 
>>> var vertices: [VertexType]
>>> var edges: [EdgeType]
>>> 
>>> func outEdges(vertex: VertexType) -> [EdgeType]
>>> 
>>> }
>>> 
>>> class GraphIterator>> Graph> {
>>> 
>>> var graph: GraphType
>>> 
>>> var startVertex: VertexType
>>> 
>>> func enter(vertex: VertexType)
>>> func propagate(along edge: EdgeType)
>>> func finish(vertex: VertexType)
>>> }
>>> 
>>> Note, how the parameter list for GraphIterator exploded, because I had to 
>>> list each level of nested types down to the VertexType, whereas
>>> in the associated types example the GraphIterator simply declares an 
>>> associated type conforming to the topmost type of my nesting, the Graph.
>>> 
>>> 
 
 Is there a deeper difference I’m missing?
>>> 
>>> Maybe Dave can chime in here?
>> 
>> You can recover an associated type (say, X.Element) by just having the type 
>> “X”, but this is not true for a type parameter. That doesn’t matter when you 
>> have (or want to specify) that type… for example, your comment that 
>> Collection and Any would basically be 
>> the same thing.
>> 
>> However, with generalized/enhanced existentials you would be able to write
>> 
>>  var heterogeneousArrayOfCollections: [Collection]
>>  heterogeneousArrayOfCollections.append([1, 2 3])
>>  heterogeneousArrayOfCollections.append([“Hello” : 1, “Swift” : 2])
>> 
>> You can’t do that with generic protocols, because there is no common element 
>> type:
>> 
>>  var heterogeneousArrayOfCollections: [Collection]
>> 
>> One could perhaps try to rely on subtyping of collections for this specific 
>> case
>> 
>>  var heterogeneousArrayOfCollections: 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-18 Thread Thorsten Seitz via swift-evolution

> Am 17.06.2016 um 16:11 schrieb Douglas Gregor :
> 
> 
>> On Jun 16, 2016, at 9:46 AM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>>> 
>>> Am 16.06.2016 um 17:36 schrieb Paul Cantrell >> >:
>>> 
 On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
 > wrote:
 
 Protocols are a mechanism for deriving types from each other whereas 
 generics are a way to parameterize types. My point was that Swift's other 
 way to parameterize types, namely by associated types, is very similar to 
 generics with wildcards when looking a the existentials of such protocols.
>>> 
>>> This has been a point of confusion for me as well. I keep hearing that 
>>> associated types are different from generic protocols, but this seems like 
>>> a distinction without a difference.
>>> 
>>> Suppose Swift allowed generic protocols. How would a hypothetical 
>>> Collection be different in practice from the proposed existential 
>>> Any?
>>> 
>>> Yes, in the realm of type theory and compiler internals they might 
>>> represented differently, sure. But in practice, in terms of what code can 
>>> actually do? I know of only two differences:
>>> 
>>> 1. A type can only conform to any given protocol with one set of type 
>>> parameters. (Nothing can be both Collection and Collection.)
>>> 
>>> 2. When a type conforms to Collection, it declares “associatedtype Foo” 
>>> instead of “: Collection”, and Foo can be inferred by the compiler in 
>>> some circumstances. That’s handy, but it’s a syntactic difference.
>> 
>> That syntactic difference is *very* handy IMO for the following reason: with 
>> generics I have to repeat all types over and over again which gets ugly when 
>> I have levels of nesting where type parameters are constrained by other 
>> generics, which requires adding their parameters to the parameter list. 
>> Essentially the nested parameters have to be fully flattened because each 
>> type parameter has to be explicitly specified.
>> 
>> I’ll try to show that with a simplified example:
>> 
>> // with associated types
>> 
>> protocol Edge {
>> associatedtype VertexType
>> 
>> var source: VertexType { get }
>> var target: VertexType { get }
>> }
>> 
>> protocol Graph {
>> associatedtype EdgeType : Edge
>> 
>> var vertices: [EdgeType.VertexType] { get }
>> var edges: [EdgeType] { get }
>> 
>> func outEdges(vertex: EdgeType.VertexType) -> [EdgeType]
>> }
>> 
>> protocol GraphIterator {
>> associatedtype GraphType : Graph
>> 
>> var graph: GraphType { get }
>> 
>> var startVertex: GraphType.VertexType { get }
>> 
>> func enter(vertex: GraphType.VertexType)
>> func propagate(along edge: GraphType.EdgeType)
>> func finish(vertex: GraphType.VertexType)
>> }
>> 
>> 
>> // with generics
>> 
>> class Edge {
>> var source: VertexType
>> var target: VertexType
>> }
>> 
>> class Graph {
>> 
>> var vertices: [VertexType]
>> var edges: [EdgeType]
>> 
>> func outEdges(vertex: VertexType) -> [EdgeType]
>> 
>> }
>> 
>> class GraphIterator> Graph> {
>> 
>> var graph: GraphType
>> 
>> var startVertex: VertexType
>> 
>> func enter(vertex: VertexType)
>> func propagate(along edge: EdgeType)
>> func finish(vertex: VertexType)
>> }
>> 
>> Note, how the parameter list for GraphIterator exploded, because I had to 
>> list each level of nested types down to the VertexType, whereas
>> in the associated types example the GraphIterator simply declares an 
>> associated type conforming to the topmost type of my nesting, the Graph.
>> 
>> 
>>> 
>>> Is there a deeper difference I’m missing?
>> 
>> Maybe Dave can chime in here?
> 
> You can recover an associated type (say, X.Element) by just having the type 
> “X”, but this is not true for a type parameter. That doesn’t matter when you 
> have (or want to specify) that type… for example, your comment that 
> Collection and Any would basically be 
> the same thing.
> 
> However, with generalized/enhanced existentials you would be able to write
> 
>   var heterogeneousArrayOfCollections: [Collection]
>   heterogeneousArrayOfCollections.append([1, 2 3])
>   heterogeneousArrayOfCollections.append([“Hello” : 1, “Swift” : 2])
> 
> You can’t do that with generic protocols, because there is no common element 
> type:
> 
>   var heterogeneousArrayOfCollections: [Collection]
> 
> One could perhaps try to rely on subtyping of collections for this specific 
> case
> 
>   var heterogeneousArrayOfCollections: [Collection]
>   heterogeneousArrayOfCollections.append([1, 2 3])
>   heterogeneousArrayOfCollections.append([“Hello” : 1, “Swift” : 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-17 Thread L Mihalkovic via swift-evolution

> On Jun 17, 2016, at 7:04 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Thu Jun 16 2016, Thorsten Seitz  > wrote:
> 
>>> Am 13.06.2016 um 04:04 schrieb Dave Abrahams :
>>> 
>>> 
>>> on Fri Jun 10 2016, Thorsten Seitz  wrote:
>>> 
> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
> :
> 
> 
>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>> :
 
>> 
>> on Wed Jun 08 2016, Jordan Rose  wrote:
>> 
 On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
  wrote:
 
 
 on Wed Jun 08 2016, Thorsten Seitz
>>> 
 >
 wrote:
 
> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> to read up again what the reasons are for that behavior).
 
 Yes, but in the case of the issue we're discussing, the choices are:
 
 1. Omit from the existential's API any protocol requirements that 
 depend
 on Self or associated types, in which case it *can't* conform to
 itself because it doesn't fulfill the requirements.
 
 2. Erase type relationships and trap at runtime when they don't line 
 up.
 
 Matthew has been arguing against #2, but you can't “fix the bug” 
 without
 it.
>>> 
>>> #1 has been my preference for a while as well, at least as a starting
>>> point.
>> 
>> I should point out that with the resyntaxing of existentials to
>> Any, the idea that Collection's existential doesn't
>> conform to Collection becomes far less absurd than it was, so maybe this
>> is not so bad.
> 
> I think the problem is more that Any does not conform to
> a specific value for a type parameter T: Collection
> 
> What I mean by this is that `Collection` denotes a type family, a
> generic parameter `T: Collection` denotes a specific (though
> unknown) member of that type family and `Any` denotes
> the type family again, so there is really no point in writing
> Any IMO.
> The type family cannot conform to T because T is just one fixed member of 
> it.
> It conforms to itself, though, as I can write
> let c1: Any = …
> let c2: Any = c1
> 
> That’s why I think that we could just drop Any and simply 
> write Collection.
 
 Let me expand that a bit:
 
 Actually all this talk about existentials vs. generics or protocols
 vs. classes has had me confused somewhat and I think there are still
 some misconceptions present on this list sometimes, so I’ll try to
 clear them up:
>>> 
>>> There are several objectively incorrect statements here, and several
>>> others with which I disagree.  I was hoping someone else would write
>>> this for me, but since the post has such a tone of authority I feel I
>>> must respond.
>> 
>> You are right, the tone of my post was not appropriate, for which I
>> want to apologize sincerely.
> 
> My fundamental disagreement is with the content, not the tone.
> 
>> I still believe my statements to be valid, though, and will respond to
>> your arguments inline. Please don't get me wrong, I'm not trying to
>> have an argument for the argument's sake. All I want is to contribute
>> maybe a tiny bit to make Swift even better than it already is, by
>> sharing ideas and thoughts not only from me but from the designs of
>> other perhaps more obscure programming languages which I happen to
>> have stumbled upon in the past (often with much delight).
> 
> And I want you to know, even though I disagree with what you've written,
> that I very much appreciate the contribution you're making.
> 
 (1) misconception: protocols with associated types are somehow very
 different from generics
 
 I don’t think they are and I will explain why. The only difference is
 the way the type parameters are bound: generics use explicit parameter
 lists whereas protocols use inheritance. That has some advantages
 (think long parameter lists of generics) and some disadvantages.
 These ways are dual in a notation sense: generic types have to have
 all parameters bound whereas protocols cannot bind any of them.
 The „existential“ notation `Any<>` being discussed on this list is
 nothing more than adding the ability to protocols to bind the
 parameters to be used just like Java’s wildcards are adding the
 opposite feature to generics, namely not having to bind all
 parameters.
>>> 
>>> Protocols and generics fulfill completely different roles in Swift, and
>>> so, **especially in a language design context like the one we're in

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-17 Thread Dave Abrahams via swift-evolution

on Thu Jun 16 2016, Thorsten Seitz  wrote:

>> Am 13.06.2016 um 04:04 schrieb Dave Abrahams :
>> 
>> 
>> on Fri Jun 10 2016, Thorsten Seitz  wrote:
>> 
 Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
 :
 
 
> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
> :
>>> 
> 
> on Wed Jun 08 2016, Jordan Rose  wrote:
> 
>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>  wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Thorsten Seitz
>> 
>>> >> >
>>> wrote:
>>> 
 Ah, thanks, I forgot!  I still consider this a bug, though (will have
 to read up again what the reasons are for that behavior).
>>> 
>>> Yes, but in the case of the issue we're discussing, the choices are:
>>> 
>>> 1. Omit from the existential's API any protocol requirements that depend
>>> on Self or associated types, in which case it *can't* conform to
>>> itself because it doesn't fulfill the requirements.
>>> 
>>> 2. Erase type relationships and trap at runtime when they don't line up.
>>> 
>>> Matthew has been arguing against #2, but you can't “fix the bug” without
>>> it.
>> 
>> #1 has been my preference for a while as well, at least as a starting
>> point.
> 
> I should point out that with the resyntaxing of existentials to
> Any, the idea that Collection's existential doesn't
> conform to Collection becomes far less absurd than it was, so maybe this
> is not so bad.
 
 I think the problem is more that Any does not conform to
 a specific value for a type parameter T: Collection
 
 What I mean by this is that `Collection` denotes a type family, a
 generic parameter `T: Collection` denotes a specific (though
 unknown) member of that type family and `Any` denotes
 the type family again, so there is really no point in writing
 Any IMO.
 The type family cannot conform to T because T is just one fixed member of 
 it.
 It conforms to itself, though, as I can write
 let c1: Any = …
 let c2: Any = c1
 
 That’s why I think that we could just drop Any and simply 
 write Collection.
>>> 
>>> Let me expand that a bit:
>>> 
>>> Actually all this talk about existentials vs. generics or protocols
>>> vs. classes has had me confused somewhat and I think there are still
>>> some misconceptions present on this list sometimes, so I’ll try to
>>> clear them up:
>> 
>> There are several objectively incorrect statements here, and several
>> others with which I disagree.  I was hoping someone else would write
>> this for me, but since the post has such a tone of authority I feel I
>> must respond.
>
> You are right, the tone of my post was not appropriate, for which I
> want to apologize sincerely.

My fundamental disagreement is with the content, not the tone.

> I still believe my statements to be valid, though, and will respond to
> your arguments inline. Please don't get me wrong, I'm not trying to
> have an argument for the argument's sake. All I want is to contribute
> maybe a tiny bit to make Swift even better than it already is, by
> sharing ideas and thoughts not only from me but from the designs of
> other perhaps more obscure programming languages which I happen to
> have stumbled upon in the past (often with much delight).

And I want you to know, even though I disagree with what you've written,
that I very much appreciate the contribution you're making.

>>> (1) misconception: protocols with associated types are somehow very
>>> different from generics
>>> 
>>> I don’t think they are and I will explain why. The only difference is
>>> the way the type parameters are bound: generics use explicit parameter
>>> lists whereas protocols use inheritance. That has some advantages
>>> (think long parameter lists of generics) and some disadvantages.
>>> These ways are dual in a notation sense: generic types have to have
>>> all parameters bound whereas protocols cannot bind any of them.
>>> The „existential“ notation `Any<>` being discussed on this list is
>>> nothing more than adding the ability to protocols to bind the
>>> parameters to be used just like Java’s wildcards are adding the
>>> opposite feature to generics, namely not having to bind all
>>> parameters.
>> 
>> Protocols and generics fulfill completely different roles in Swift, and
>> so, **especially in a language design context like the one we're in
>> here**, must be thought of differently.  The former are an abstraction
>> mechanism for APIs, and the latter a mechanism for generalizing
>> implementations.  
>
> That's not what I was talking about. Of course, protocols are a
> mechanism for deriving types from each other whereas 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-17 Thread Douglas Gregor via swift-evolution

> On Jun 16, 2016, at 9:46 AM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
>> 
>> Am 16.06.2016 um 17:36 schrieb Paul Cantrell > >:
>> 
>>> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>>> > wrote:
>>> 
>>> Protocols are a mechanism for deriving types from each other whereas 
>>> generics are a way to parameterize types. My point was that Swift's other 
>>> way to parameterize types, namely by associated types, is very similar to 
>>> generics with wildcards when looking a the existentials of such protocols.
>> 
>> This has been a point of confusion for me as well. I keep hearing that 
>> associated types are different from generic protocols, but this seems like a 
>> distinction without a difference.
>> 
>> Suppose Swift allowed generic protocols. How would a hypothetical 
>> Collection be different in practice from the proposed existential 
>> Any?
>> 
>> Yes, in the realm of type theory and compiler internals they might 
>> represented differently, sure. But in practice, in terms of what code can 
>> actually do? I know of only two differences:
>> 
>> 1. A type can only conform to any given protocol with one set of type 
>> parameters. (Nothing can be both Collection and Collection.)
>> 
>> 2. When a type conforms to Collection, it declares “associatedtype Foo” 
>> instead of “: Collection”, and Foo can be inferred by the compiler in 
>> some circumstances. That’s handy, but it’s a syntactic difference.
> 
> That syntactic difference is *very* handy IMO for the following reason: with 
> generics I have to repeat all types over and over again which gets ugly when 
> I have levels of nesting where type parameters are constrained by other 
> generics, which requires adding their parameters to the parameter list. 
> Essentially the nested parameters have to be fully flattened because each 
> type parameter has to be explicitly specified.
> 
> I’ll try to show that with a simplified example:
> 
> // with associated types
> 
> protocol Edge {
> associatedtype VertexType
> 
> var source: VertexType { get }
> var target: VertexType { get }
> }
> 
> protocol Graph {
> associatedtype EdgeType : Edge
> 
> var vertices: [EdgeType.VertexType] { get }
> var edges: [EdgeType] { get }
> 
> func outEdges(vertex: EdgeType.VertexType) -> [EdgeType]
> }
> 
> protocol GraphIterator {
> associatedtype GraphType : Graph
> 
> var graph: GraphType { get }
> 
> var startVertex: GraphType.VertexType { get }
> 
> func enter(vertex: GraphType.VertexType)
> func propagate(along edge: GraphType.EdgeType)
> func finish(vertex: GraphType.VertexType)
> }
> 
> 
> // with generics
> 
> class Edge {
> var source: VertexType
> var target: VertexType
> }
> 
> class Graph {
> 
> var vertices: [VertexType]
> var edges: [EdgeType]
> 
> func outEdges(vertex: VertexType) -> [EdgeType]
> 
> }
> 
> class GraphIterator Graph> {
> 
> var graph: GraphType
> 
> var startVertex: VertexType
> 
> func enter(vertex: VertexType)
> func propagate(along edge: EdgeType)
> func finish(vertex: VertexType)
> }
> 
> Note, how the parameter list for GraphIterator exploded, because I had to 
> list each level of nested types down to the VertexType, whereas
> in the associated types example the GraphIterator simply declares an 
> associated type conforming to the topmost type of my nesting, the Graph.
> 
> 
>> 
>> Is there a deeper difference I’m missing?
> 
> Maybe Dave can chime in here?

You can recover an associated type (say, X.Element) by just having the type 
“X”, but this is not true for a type parameter. That doesn’t matter when you 
have (or want to specify) that type… for example, your comment that 
Collection and Any would basically be 
the same thing.

However, with generalized/enhanced existentials you would be able to write

var heterogeneousArrayOfCollections: [Collection]
heterogeneousArrayOfCollections.append([1, 2 3])
heterogeneousArrayOfCollections.append([“Hello” : 1, “Swift” : 2])

You can’t do that with generic protocols, because there is no common element 
type:

var heterogeneousArrayOfCollections: [Collection]

One could perhaps try to rely on subtyping of collections for this specific case

var heterogeneousArrayOfCollections: [Collection]
heterogeneousArrayOfCollections.append([1, 2 3])
heterogeneousArrayOfCollections.append([“Hello” : 1, “Swift” : 2])

but that’s not something we have now and doesn’t really generalize well in 
Swift.

- Doug


___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-16 Thread Thorsten Seitz via swift-evolution

> Am 16.06.2016 um 17:36 schrieb Paul Cantrell :
> 
>> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>> Protocols are a mechanism for deriving types from each other whereas 
>> generics are a way to parameterize types. My point was that Swift's other 
>> way to parameterize types, namely by associated types, is very similar to 
>> generics with wildcards when looking a the existentials of such protocols.
> 
> This has been a point of confusion for me as well. I keep hearing that 
> associated types are different from generic protocols, but this seems like a 
> distinction without a difference.
> 
> Suppose Swift allowed generic protocols. How would a hypothetical 
> Collection be different in practice from the proposed existential 
> Any?
> 
> Yes, in the realm of type theory and compiler internals they might 
> represented differently, sure. But in practice, in terms of what code can 
> actually do? I know of only two differences:
> 
> 1. A type can only conform to any given protocol with one set of type 
> parameters. (Nothing can be both Collection and Collection.)
> 
> 2. When a type conforms to Collection, it declares “associatedtype Foo” 
> instead of “: Collection”, and Foo can be inferred by the compiler in 
> some circumstances. That’s handy, but it’s a syntactic difference.

That syntactic difference is *very* handy IMO for the following reason: with 
generics I have to repeat all types over and over again which gets ugly when I 
have levels of nesting where type parameters are constrained by other generics, 
which requires adding their parameters to the parameter list. Essentially the 
nested parameters have to be fully flattened because each type parameter has to 
be explicitly specified.

I’ll try to show that with a simplified example:

// with associated types

protocol Edge {
associatedtype VertexType

var source: VertexType { get }
var target: VertexType { get }
}

protocol Graph {
associatedtype EdgeType : Edge

var vertices: [EdgeType.VertexType] { get }
var edges: [EdgeType] { get }

func outEdges(vertex: EdgeType.VertexType) -> [EdgeType]
}

protocol GraphIterator {
associatedtype GraphType : Graph

var graph: GraphType { get }

var startVertex: GraphType.VertexType { get }

func enter(vertex: GraphType.VertexType)
func propagate(along edge: GraphType.EdgeType)
func finish(vertex: GraphType.VertexType)
}


// with generics

class Edge {
var source: VertexType
var target: VertexType
}

class Graph {

var vertices: [VertexType]
var edges: [EdgeType]

func outEdges(vertex: VertexType) -> [EdgeType]

}

class GraphIterator> {

var graph: GraphType

var startVertex: VertexType

func enter(vertex: VertexType)
func propagate(along edge: EdgeType)
func finish(vertex: VertexType)
}

Note, how the parameter list for GraphIterator exploded, because I had to list 
each level of nested types down to the VertexType, whereas
in the associated types example the GraphIterator simply declares an associated 
type conforming to the topmost type of my nesting, the Graph.


> 
> Is there a deeper difference I’m missing?

Maybe Dave can chime in here?


-Thorsten

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-16 Thread L. Mihalkovic via swift-evolution


> On Jun 16, 2016, at 5:36 PM, Paul Cantrell via swift-evolution 
>  wrote:
> 
>> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>>  wrote:
>> 
>> Protocols are a mechanism for deriving types from each other whereas 
>> generics are a way to parameterize types. My point was that Swift's other 
>> way to parameterize types, namely by associated types, is very similar to 
>> generics with wildcards when looking a the existentials of such protocols.
> 
> This has been a point of confusion for me as well. I keep hearing that 
> associated types are different from generic protocols, but this seems like a 
> distinction without a difference.
> 
> Suppose Swift allowed generic protocols. How would a hypothetical 
> Collection be different in practice from the proposed existential 
> Any?
> 
> Yes, in the realm of type theory and compiler internals they might 
> represented differently, sure. But in practice, in terms of what code can 
> actually do? I know of only two differences:
> 
> 1. A type can only conform to any given protocol with one set of type 
> parameters. (Nothing can be both Collection and Collection.)
> 
> 2. When a type conforms to Collection, it declares “associatedtype Foo” 
> instead of “: Collection”, and Foo can be inferred by the compiler in 
> some circumstances. That’s handy, but it’s a syntactic difference.

Wasn't there something recently from chris about removing inference?

> 
> Is there a deeper difference I’m missing?
> 
> Cheers, P
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-16 Thread Austin Zheng via swift-evolution

> On Jun 16, 2016, at 8:55 AM, Paul Cantrell via swift-evolution 
>  wrote:
> 
> Right. Is that it? Are associated types really just generic protocols + 
> single conformance constraint + type params inferred / implied?

A protocol and its associated types form a "package" or "group" of types that 
function together as one cohesive unit. For example, in the Swift world a 
collection is defined not only by its element type, but also by the type of its 
subsequence and its index. The protocol and associated types together define 
how the various types in the group relate to each other (via associated type 
nesting; for example Element belongs to Iterator belongs to Sequence), and to 
other types (via protocol conformance constraints).

A type doesn't need to be generic to adopt a protocol + associated types. For 
example, the various String views are bona fide Collections, but they're not 
generic in any way: all their associated types are fixed to concrete types as 
far as I can tell.

Another way to think of it is that generics allow *instances* to be abstracted 
over type, while protocols+associated types allow *conforming types* to be 
abstracted over type. For example, Either can be instantiated for one 
instance as Either, and for another as Either. (A 
simplified example version of the) protocol Collection can be instantiated for 
one type as being (Collection.Element = Int, Collection.Index = FooIndex), and 
another type as being (Collection.Element = String, Collection.Index = Int).

A generic type conforming to Collection would "unify" the two concepts. For 
example, SimpleArray instantiates Collection as being (Collection.Element = 
T, Collection.Index = Int). Then, individual instances of SimpleArray 
abstract over T by filling in T with Int (SimpleArray), String, etc.

Hope that helps,
Austin

> 
> P
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-16 Thread L. Mihalkovic via swift-evolution


> On Jun 16, 2016, at 3:29 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
> 
>> Am 13.06.2016 um 04:04 schrieb Dave Abrahams :
>> 
>> 
>> on Fri Jun 10 2016, Thorsten Seitz  wrote:
>> 
 Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
 :
 
 
> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
> :
>>> 
> 
> on Wed Jun 08 2016, Jordan Rose  wrote:
> 
>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>  wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Thorsten Seitz
>> 
>>> >> >
>>> wrote:
>>> 
 Ah, thanks, I forgot!  I still consider this a bug, though (will have
 to read up again what the reasons are for that behavior).
>>> 
>>> Yes, but in the case of the issue we're discussing, the choices are:
>>> 
>>> 1. Omit from the existential's API any protocol requirements that depend
>>> on Self or associated types, in which case it *can't* conform to
>>> itself because it doesn't fulfill the requirements.
>>> 
>>> 2. Erase type relationships and trap at runtime when they don't line up.
>>> 
>>> Matthew has been arguing against #2, but you can't “fix the bug” without
>>> it.
>> 
>> #1 has been my preference for a while as well, at least as a starting
>> point.
> 
> I should point out that with the resyntaxing of existentials to
> Any, the idea that Collection's existential doesn't
> conform to Collection becomes far less absurd than it was, so maybe this
> is not so bad.
 
 I think the problem is more that Any does not conform to
 a specific value for a type parameter T: Collection
 
 What I mean by this is that `Collection` denotes a type family, a
 generic parameter `T: Collection` denotes a specific (though
 unknown) member of that type family and `Any` denotes
 the type family again, so there is really no point in writing
 Any IMO.
 The type family cannot conform to T because T is just one fixed member of 
 it.
 It conforms to itself, though, as I can write
 let c1: Any = …
 let c2: Any = c1
 
 That’s why I think that we could just drop Any and simply 
 write Collection.
>>> 
>>> Let me expand that a bit:
>>> 
>>> Actually all this talk about existentials vs. generics or protocols
>>> vs. classes has had me confused somewhat and I think there are still
>>> some misconceptions present on this list sometimes, so I’ll try to
>>> clear them up:
>> 
>> There are several objectively incorrect statements here, and several
>> others with which I disagree.  I was hoping someone else would write
>> this for me, but since the post has such a tone of authority I feel I
>> must respond.
> 
> You are right, the tone of my post was not appropriate, for which I want to 
> apologize sincerely.
> 
> I still believe my statements to be valid, though, and will respond to your 
> arguments inline. Please don't get me wrong, I'm not trying to have an 
> argument for the argument's sake. All I want is to contribute maybe a tiny 
> bit to make Swift even better than it already is, by sharing ideas and 
> thoughts not only from me but from the designs of other perhaps more obscure 
> programming languages which I happen to have stumbled upon in the past (often 
> with much delight). 
> 
>> 
>>> (1) misconception: protocols with associated types are somehow very
>>> different from generics
>>> 
>>> I don’t think they are and I will explain why. The only difference is
>>> the way the type parameters are bound: generics use explicit parameter
>>> lists whereas protocols use inheritance. That has some advantages
>>> (think long parameter lists of generics) and some disadvantages.
>>> These ways are dual in a notation sense: generic types have to have
>>> all parameters bound whereas protocols cannot bind any of them.
>>> The „existential“ notation `Any<>` being discussed on this list is
>>> nothing more than adding the ability to protocols to bind the
>>> parameters to be used just like Java’s wildcards are adding the
>>> opposite feature to generics, namely not having to bind all
>>> parameters.
>> 
>> Protocols and generics fulfill completely different roles in Swift, and
>> so, **especially in a language design context like the one we're in
>> here**, must be thought of differently.  The former are an abstraction
>> mechanism for APIs, and the latter a mechanism for generalizing
>> implementations.  
> 
> That's not what I was talking about. Of course, protocols are a mechanism for 
> deriving types from each other whereas generics are a way to parameterize 
> types. My point was that Swift's other way to parameterize types, namely by 
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-16 Thread Paul Cantrell via swift-evolution

> On Jun 16, 2016, at 10:50 AM, Matthew Johnson  wrote:
> 
>> 
>> On Jun 16, 2016, at 10:36 AM, Paul Cantrell via swift-evolution 
>> > wrote:
>> 
>> This has been a point of confusion for me as well. I keep hearing that 
>> associated types are different from generic protocols, but this seems like a 
>> distinction without a difference.
>> 
>> Suppose Swift allowed generic protocols. How would a hypothetical 
>> Collection be different in practice from the proposed existential 
>> Any?
> 
> If Collection were a Java-like generic protocol you would have 5 generic 
> parameters, all of which must be explicitly provided with arguments when 
> forming an existential, although the arguments could be wildcards.  This is a 
> bit unwieldy.

Yes. This was #2 on my list. A very, very nice syntactic difference — 
nonrepetition of redundant type information is so much of what makes Swift 
great. — but only a syntactic difference.


>> Yes, in the realm of type theory and compiler internals they might 
>> represented differently, sure. But in practice, in terms of what code can 
>> actually do? I know of only two differences:
>> 
>> 1. A type can only conform to any given protocol with one set of type 
>> parameters. (Nothing can be both Collection and Collection.)
> 
> This is a pretty huge difference.  Multiple conformances are on the unlikely 
> list for Swift and generic protocol syntax implies multiple conformances are 
> possible (as is the case in at least some languages).

Right. Is that it? Are associated types really just generic protocols + single 
conformance constraint + type params inferred / implied?

P___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-16 Thread Matthew Johnson via swift-evolution

> On Jun 16, 2016, at 10:36 AM, Paul Cantrell via swift-evolution 
>  wrote:
> 
>> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>> Protocols are a mechanism for deriving types from each other whereas 
>> generics are a way to parameterize types. My point was that Swift's other 
>> way to parameterize types, namely by associated types, is very similar to 
>> generics with wildcards when looking a the existentials of such protocols.
> 
> This has been a point of confusion for me as well. I keep hearing that 
> associated types are different from generic protocols, but this seems like a 
> distinction without a difference.
> 
> Suppose Swift allowed generic protocols. How would a hypothetical 
> Collection be different in practice from the proposed existential 
> Any?

If Collection were a Java-like generic protocol you would have 5 generic 
parameters, all of which must be explicitly provided with arguments when 
forming an existential, although the arguments could be wildcards.  This is a 
bit unwieldy.  You would probably end up using a typealias in either case.

> 
> Yes, in the realm of type theory and compiler internals they might 
> represented differently, sure. But in practice, in terms of what code can 
> actually do? I know of only two differences:
> 
> 1. A type can only conform to any given protocol with one set of type 
> parameters. (Nothing can be both Collection and Collection.)

This is a pretty huge difference.  Multiple conformances are on the unlikely 
list for Swift and generic protocol syntax implies multiple conformances are 
possible (as is the case in at least some languages).

> 
> 2. When a type conforms to Collection, it declares “associatedtype Foo” 
> instead of “: Collection”, and Foo can be inferred by the compiler in 
> some circumstances. That’s handy, but it’s a syntactic difference.
> 
> Is there a deeper difference I’m missing?

> 
> Cheers, P
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-16 Thread Paul Cantrell via swift-evolution
> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> Protocols are a mechanism for deriving types from each other whereas generics 
> are a way to parameterize types. My point was that Swift's other way to 
> parameterize types, namely by associated types, is very similar to generics 
> with wildcards when looking a the existentials of such protocols.

This has been a point of confusion for me as well. I keep hearing that 
associated types are different from generic protocols, but this seems like a 
distinction without a difference.

Suppose Swift allowed generic protocols. How would a hypothetical 
Collection be different in practice from the proposed existential 
Any?

Yes, in the realm of type theory and compiler internals they might represented 
differently, sure. But in practice, in terms of what code can actually do? I 
know of only two differences:

1. A type can only conform to any given protocol with one set of type 
parameters. (Nothing can be both Collection and Collection.)

2. When a type conforms to Collection, it declares “associatedtype Foo” instead 
of “: Collection”, and Foo can be inferred by the compiler in some 
circumstances. That’s handy, but it’s a syntactic difference.

Is there a deeper difference I’m missing?

Cheers, P

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-13 Thread L Mihalkovic via swift-evolution
I had decided to watch from the sideline, but a couple things push me to say 
something


> On Jun 13, 2016, at 4:04 AM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Fri Jun 10 2016, Thorsten Seitz  > wrote:
> 
>>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>>> :
>>> 
>>> 
 Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
 :
 
>> 
 
 on Wed Jun 08 2016, Jordan Rose  wrote:
 
>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz
> 
>> > >
>> wrote:
>> 
>>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices are:
>> 
>> 1. Omit from the existential's API any protocol requirements that depend
>> on Self or associated types, in which case it *can't* conform to
>> itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't line up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” without
>> it.
> 
> #1 has been my preference for a while as well, at least as a starting
> point. 
 
 I should point out that with the resyntaxing of existentials to
 Any, the idea that Collection's existential doesn't
 conform to Collection becomes far less absurd than it was, so maybe this
 is not so bad.
>>> 
>>> I think the problem is more that Any does not conform to
>>> a specific value for a type parameter T: Collection
>>> 
>>> What I mean by this is that `Collection` denotes a type family, a
>>> generic parameter `T: Collection` denotes a specific (though
>>> unknown) member of that type family and `Any` denotes
>>> the type family again, so there is really no point in writing
>>> Any IMO.
>>> The type family cannot conform to T because T is just one fixed member of 
>>> it.
>>> It conforms to itself, though, as I can write
>>> let c1: Any = …
>>> let c2: Any = c1
>>> 
>>> That’s why I think that we could just drop Any and simply write 
>>> Collection.
>> 
>> Let me expand that a bit:
>> 
>> Actually all this talk about existentials vs. generics or protocols
>> vs. classes has had me confused somewhat and I think there are still
>> some misconceptions present on this list sometimes, so I’ll try to
>> clear them up:
> 
> There are several objectively incorrect statements here, and several
> others with which I disagree.  I was hoping someone else would write
> this for me, but since the post has such a tone of authority I feel I
> must respond.
> 
>> (1) misconception: protocols with associated types are somehow very
>> different from generics
>> 
>> I don’t think they are and I will explain why. The only difference is
>> the way the type parameters are bound: generics use explicit parameter
>> lists whereas protocols use inheritance. That has some advantages
>> (think long parameter lists of generics) and some disadvantages.
>> These ways are dual in a notation sense: generic types have to have
>> all parameters bound whereas protocols cannot bind any of them.
>> The „existential“ notation `Any<>` being discussed on this list is
>> nothing more than adding the ability to protocols to bind the
>> parameters to be used just like Java’s wildcards are adding the
>> opposite feature to generics, namely not having to bind all
>> parameters.
> 
> Protocols and generics fulfill completely different roles in Swift, and
> so, **especially in a language design context like the one we're in
> here**, must be thought of differently.  

The temptation is great to mention your own words from 2+ years ago regarding 
the choice of the name Protocol instead of Interface, and the ‘hope’ (your 
word) that the differentiation would wind-up being big enough to justify the 
new name. Wanting to view them in a different light is one thing, succeeding in 
establishing a gap wide enough that people with superficial or intimate 
knowledge of both would come to the unavoidable conclusion that they are 
fundamentally different, is an entirely different exercise.

At this point I think it is fair to say that the differences are notable but, 
perhaps out of lack of familiarity with the details, not quite strong enough to 
make all developers reach the conclusion you’d like them to reach.

> The former are an abstraction
> mechanism for APIs, and the latter a mechanism for generalizing
> implementations. The only place you could argue that they intersect is
> in generic non-final classes, because a class fills the dual role of
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-13 Thread Goffredo Marocchi via swift-evolution
Hello Dave,

Sent from my iPhone

> On 13 Jun 2016, at 03:04, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Fri Jun 10 2016, Thorsten Seitz  wrote:
> 
>>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>>> :
>>> 
>>> 
 Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
 :
>> 
 
 on Wed Jun 08 2016, Jordan Rose  wrote:
 
>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz
> 
>> > >
>> wrote:
>> 
>>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices are:
>> 
>> 1. Omit from the existential's API any protocol requirements that depend
>> on Self or associated types, in which case it *can't* conform to
>> itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't line up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” without
>> it.
> 
> #1 has been my preference for a while as well, at least as a starting
> point.
 
 I should point out that with the resyntaxing of existentials to
 Any, the idea that Collection's existential doesn't
 conform to Collection becomes far less absurd than it was, so maybe this
 is not so bad.
>>> 
>>> I think the problem is more that Any does not conform to
>>> a specific value for a type parameter T: Collection
>>> 
>>> What I mean by this is that `Collection` denotes a type family, a
>>> generic parameter `T: Collection` denotes a specific (though
>>> unknown) member of that type family and `Any` denotes
>>> the type family again, so there is really no point in writing
>>> Any IMO.
>>> The type family cannot conform to T because T is just one fixed member of 
>>> it.
>>> It conforms to itself, though, as I can write
>>> let c1: Any = …
>>> let c2: Any = c1
>>> 
>>> That’s why I think that we could just drop Any and simply write 
>>> Collection.
>> 
>> Let me expand that a bit:
>> 
>> Actually all this talk about existentials vs. generics or protocols
>> vs. classes has had me confused somewhat and I think there are still
>> some misconceptions present on this list sometimes, so I’ll try to
>> clear them up:
> 
> There are several objectively incorrect statements here, and several
> others with which I disagree.  I was hoping someone else would write
> this for me, but since the post has such a tone of authority I feel I
> must respond.
> 
>> (1) misconception: protocols with associated types are somehow very
>> different from generics
>> 
>> I don’t think they are and I will explain why. The only difference is
>> the way the type parameters are bound: generics use explicit parameter
>> lists whereas protocols use inheritance. That has some advantages
>> (think long parameter lists of generics) and some disadvantages.
>> These ways are dual in a notation sense: generic types have to have
>> all parameters bound whereas protocols cannot bind any of them.
>> The „existential“ notation `Any<>` being discussed on this list is
>> nothing more than adding the ability to protocols to bind the
>> parameters to be used just like Java’s wildcards are adding the
>> opposite feature to generics, namely not having to bind all
>> parameters.
> 
> Protocols and generics fulfill completely different roles in Swift, and
> so, **especially in a language design context like the one we're in
> here**, must be thought of differently.  The former are an abstraction
> mechanism for APIs, and the latter a mechanism for generalizing
> implementations.  The only place you could argue that they intersect is
> in generic non-final classes, because a class fills the dual role of
> abstraction and implementation mechanism (and some might say that's a
> weakness).  But even accounting for generic classes, protocols with
> associated types are very different from generics.  Two utterly
> different types (an enum and a struct, for example) can conform to any
> given protocol P, but generic types always share a common basis
> implementation.  There is no way to produce distinct instances of a
> generic type with all its type parameters bound, but for any protocol P
> I can make infinitely many instances of P with P.AssociatedType == Int.
> 
> Back to the my original point: while protocols and generic types have
> some similarities, the idea that they are fundamentally the same thing
> (I know you didn't say *exactly* that, but I think it will be read that
> way) would be wrong and a very unproductive way to approach language
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-13 Thread Dave Abrahams via swift-evolution

on Sat Jun 11 2016, Jonathan Hull  wrote:

>> If your code has many manual type erasing wrappers corresponding to
>> protocols with associated types and/or Self requirements that also never
>> have to trap type mismatches, that would certainly be instructive
>> empirical data.  Would you care to share the protocols and wrappers you
>> are talking about?
> This code is a bit embarrassing (I wrote most of it as I was still
> learning Swift), but if it is helpful I will share:
> https://gist.github.com/jonhull/639e756ad5228348f93f40f06169588c
>
> It doesn’t trap anywhere (that I know about). Some of the code which
> calls it does throw an error in the case of mismatched types (but it
> doesn’t/shouldn't crash).  

If that error is being thrown to handle what you consider to be a
programming error, that is the moral equivalent of a trap.

> Most functions which use it are generic on the associatedType.
>
> It does work fairly well though (even on the AppleWatch).  The main
> issue is that I have no way to persist the values which have been
> drawn into the type-erased world (or even the value-type world,
> really).
>
> Also, if anyone has a better way to write the type erasing wrapper, I
> would love to hear it. These are very memory intensive…

It looks like you could make some gains by, instead of storing a closure
for each operation, using a base class with a method for each operation,
per the box types in
https://github.com/apple/swift/blob/master/stdlib/public/core/ExistentialCollection.swift.gyb

HTH,
-- 
Dave
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-12 Thread Dave Abrahams via swift-evolution

on Sun Jun 12 2016, L Mihalkovic  wrote:

> My understanding is that dave is the type system designer.

That would be a misunderstanding.  I am a contributor, but other people
take the lead on the type system.

-- 
Dave
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-12 Thread Dave Abrahams via swift-evolution

on Fri Jun 10 2016, Thorsten Seitz  wrote:

>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>> :
>> 
>> 
>>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>>> :
>>> 
>
>>> 
>>> on Wed Jun 08 2016, Jordan Rose  wrote:
>>> 
> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>  wrote:
> 
> 
> on Wed Jun 08 2016, Thorsten Seitz
 
>  >
> wrote:
> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices are:
> 
> 1. Omit from the existential's API any protocol requirements that depend
> on Self or associated types, in which case it *can't* conform to
> itself because it doesn't fulfill the requirements.
> 
> 2. Erase type relationships and trap at runtime when they don't line up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” without
> it.
 
 #1 has been my preference for a while as well, at least as a starting
 point. 
>>> 
>>> I should point out that with the resyntaxing of existentials to
>>> Any, the idea that Collection's existential doesn't
>>> conform to Collection becomes far less absurd than it was, so maybe this
>>> is not so bad.
>> 
>> I think the problem is more that Any does not conform to
>> a specific value for a type parameter T: Collection
>> 
>> What I mean by this is that `Collection` denotes a type family, a
>> generic parameter `T: Collection` denotes a specific (though
>> unknown) member of that type family and `Any` denotes
>> the type family again, so there is really no point in writing
>> Any IMO.
>> The type family cannot conform to T because T is just one fixed member of it.
>> It conforms to itself, though, as I can write
>> let c1: Any = …
>> let c2: Any = c1
>> 
>> That’s why I think that we could just drop Any and simply write 
>> Collection.
>
> Let me expand that a bit:
>
> Actually all this talk about existentials vs. generics or protocols
> vs. classes has had me confused somewhat and I think there are still
> some misconceptions present on this list sometimes, so I’ll try to
> clear them up:

There are several objectively incorrect statements here, and several
others with which I disagree.  I was hoping someone else would write
this for me, but since the post has such a tone of authority I feel I
must respond.

> (1) misconception: protocols with associated types are somehow very
> different from generics
>
> I don’t think they are and I will explain why. The only difference is
> the way the type parameters are bound: generics use explicit parameter
> lists whereas protocols use inheritance. That has some advantages
> (think long parameter lists of generics) and some disadvantages.
> These ways are dual in a notation sense: generic types have to have
> all parameters bound whereas protocols cannot bind any of them.
> The „existential“ notation `Any<>` being discussed on this list is
> nothing more than adding the ability to protocols to bind the
> parameters to be used just like Java’s wildcards are adding the
> opposite feature to generics, namely not having to bind all
> parameters.

Protocols and generics fulfill completely different roles in Swift, and
so, **especially in a language design context like the one we're in
here**, must be thought of differently.  The former are an abstraction
mechanism for APIs, and the latter a mechanism for generalizing
implementations.  The only place you could argue that they intersect is
in generic non-final classes, because a class fills the dual role of
abstraction and implementation mechanism (and some might say that's a
weakness).  But even accounting for generic classes, protocols with
associated types are very different from generics.  Two utterly
different types (an enum and a struct, for example) can conform to any
given protocol P, but generic types always share a common basis
implementation.  There is no way to produce distinct instances of a
generic type with all its type parameters bound, but for any protocol P
I can make infinitely many instances of P with P.AssociatedType == Int.

Back to the my original point: while protocols and generic types have
some similarities, the idea that they are fundamentally the same thing
(I know you didn't say *exactly* that, but I think it will be read that
way) would be wrong and a very unproductive way to approach language
evolution.

> Essentially `Any` in Swift is just the same as
> `Collection` in Java (assuming for comparability’s sake that
> Swift’s Collection had no additional associated types; otherwise I
> would just have to introduce a Collection in Java).

I don't see how 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-12 Thread Thorsten Seitz via swift-evolution

> Am 12.06.2016 um 17:40 schrieb L Mihalkovic :
> 
>> 
>> On Jun 12, 2016, at 4:05 PM, Thorsten Seitz > > wrote:
>> 
>>> 
>>> Am 12.06.2016 um 09:21 schrieb L. Mihalkovic >> >:
>>> 
>>> 
>>> 
>>> 
>>> Regards
>>> (From mobile)
>>> On Jun 11, 2016, at 11:43 PM, Thorsten Seitz >> > wrote:
>>> 
 
 
> Am 11.06.2016 um 15:08 schrieb L. Mihalkovic 
> >:
> 
> 
>> On Jun 11, 2016, at 2:05 PM, Thorsten Seitz > > wrote:
>> 
>> 
>>> Am 11.06.2016 um 12:38 schrieb L. Mihalkovic 
>>> >:
>>> 
>>> 
 On Jun 11, 2016, at 11:30 AM, Thorsten Seitz > wrote:
 
 
> Am 11.06.2016 um 08:00 schrieb L. Mihalkovic 
> >:
> 
> 
> 
> 
> Regards
> (From mobile)
>> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>> 
>>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>>> >:
>>> 
>>> 
 Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
 >:
 
 
 on Wed Jun 08 2016, Jordan Rose > wrote:
 
>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>> > 
>> wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz
> 
>> 
>> > >>
>> wrote:
>> 
>>> Ah, thanks, I forgot!  I still consider this a bug, though 
>>> (will have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices 
>> are:
>> 
>> 1. Omit from the existential's API any protocol requirements 
>> that depend
>> on Self or associated types, in which case it *can't* conform to
>> itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't 
>> line up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” 
>> without
>> it.
> 
> #1 has been my preference for a while as well, at least as a 
> starting
> point.
 
 I should point out that with the resyntaxing of existentials to
 Any, the idea that Collection's existential doesn't
 conform to Collection becomes far less absurd than it was, so 
 maybe this
 is not so bad.
>>> 
>>> I think the problem is more that Any does not conform 
>>> to a specific value for a type parameter T: Collection
>>> 
>>> What I mean by this is that `Collection` denotes a type family, a 
>>> generic parameter `T: Collection` denotes a specific (though 
>>> unknown) member of that type family and `Any` denotes 
>>> the type family again, so there is really no point in writing 
>>> Any IMO. 
>>> The type family cannot conform to T because T is just one fixed 
>>> member of it.
>>> It conforms to itself, though, as I can write
>>> let c1: Any = …
>>> let c2: Any = c1
>>> 
>>> That’s why I think that we could just drop Any and 
>>> simply write Collection.
>> 
>> 
>> Let me expand that a bit:
>> 
>> Actually all this talk about existentials vs. generics or protocols 
>> vs. classes has had me confused somewhat and I think there are still 
>> some misconceptions present on this list sometimes, so I’ll try to 
>> clear them up:
>> 
>> (1) misconception: protocols with associated types are somehow very 
>> different from generics
>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-12 Thread L Mihalkovic via swift-evolution

> On Jun 12, 2016, at 4:05 PM, Thorsten Seitz  wrote:
> 
>> 
>> Am 12.06.2016 um 09:21 schrieb L. Mihalkovic > >:
>> 
>> 
>> 
>> 
>> Regards
>> (From mobile)
>> On Jun 11, 2016, at 11:43 PM, Thorsten Seitz > > wrote:
>> 
>>> 
>>> 
 Am 11.06.2016 um 15:08 schrieb L. Mihalkovic >:
 
 
> On Jun 11, 2016, at 2:05 PM, Thorsten Seitz  > wrote:
> 
> 
>> Am 11.06.2016 um 12:38 schrieb L. Mihalkovic 
>> >:
>> 
>> 
>>> On Jun 11, 2016, at 11:30 AM, Thorsten Seitz >> > wrote:
>>> 
>>> 
 Am 11.06.2016 um 08:00 schrieb L. Mihalkovic 
 >:
 
 
 
 
 Regards
 (From mobile)
> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
> > wrote:
> 
> 
>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>> >:
>> 
>> 
>>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>>> >:
>>> 
>>> 
>>> on Wed Jun 08 2016, Jordan Rose >> > wrote:
>>> 
> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
> > 
> wrote:
> 
> 
> on Wed Jun 08 2016, Thorsten Seitz
 
> 
>  >>
> wrote:
> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will 
>> have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices 
> are:
> 
> 1. Omit from the existential's API any protocol requirements that 
> depend
> on Self or associated types, in which case it *can't* conform to
> itself because it doesn't fulfill the requirements.
> 
> 2. Erase type relationships and trap at runtime when they don't 
> line up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” 
> without
> it.
 
 #1 has been my preference for a while as well, at least as a 
 starting
 point.
>>> 
>>> I should point out that with the resyntaxing of existentials to
>>> Any, the idea that Collection's existential doesn't
>>> conform to Collection becomes far less absurd than it was, so maybe 
>>> this
>>> is not so bad.
>> 
>> I think the problem is more that Any does not conform to 
>> a specific value for a type parameter T: Collection
>> 
>> What I mean by this is that `Collection` denotes a type family, a 
>> generic parameter `T: Collection` denotes a specific (though 
>> unknown) member of that type family and `Any` denotes 
>> the type family again, so there is really no point in writing 
>> Any IMO. 
>> The type family cannot conform to T because T is just one fixed 
>> member of it.
>> It conforms to itself, though, as I can write
>> let c1: Any = …
>> let c2: Any = c1
>> 
>> That’s why I think that we could just drop Any and 
>> simply write Collection.
> 
> 
> Let me expand that a bit:
> 
> Actually all this talk about existentials vs. generics or protocols 
> vs. classes has had me confused somewhat and I think there are still 
> some misconceptions present on this list sometimes, so I’ll try to 
> clear them up:
> 
> (1) misconception: protocols with associated types are somehow very 
> different from generics
> 
> I don’t think they are and I will explain why. The only difference is 
> the way the type parameters are bound: generics use explicit 
> parameter lists whereas protocols use inheritance. That has some 
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-12 Thread L. Mihalkovic via swift-evolution

> On Jun 12, 2016, at 4:05 PM, Thorsten Seitz  wrote:
> 
> 
>> Am 12.06.2016 um 09:21 schrieb L. Mihalkovic :
>> 
>> 
>> 
>> 
>> Regards
>> (From mobile)
>> On Jun 11, 2016, at 11:43 PM, Thorsten Seitz  wrote:
>> 
>>> 
>>> 
 Am 11.06.2016 um 15:08 schrieb L. Mihalkovic 
 :
 
 
> On Jun 11, 2016, at 2:05 PM, Thorsten Seitz  wrote:
> 
> 
>> Am 11.06.2016 um 12:38 schrieb L. Mihalkovic 
>> :
>> 
>> 
>>> On Jun 11, 2016, at 11:30 AM, Thorsten Seitz  
>>> wrote:
>>> 
>>> 
 Am 11.06.2016 um 08:00 schrieb L. Mihalkovic 
 :
 
 
 
 
 Regards
 (From mobile)
> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>> :
>> 
>> 
>>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>>> :
>>> 
>>> 
>>> on Wed Jun 08 2016, Jordan Rose  wrote:
>>> 
> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>  wrote:
> 
> 
> on Wed Jun 08 2016, Thorsten Seitz
 
>  >
> wrote:
> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will 
>> have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices 
> are:
> 
> 1. Omit from the existential's API any protocol requirements that 
> depend
> on Self or associated types, in which case it *can't* conform to
> itself because it doesn't fulfill the requirements.
> 
> 2. Erase type relationships and trap at runtime when they don't 
> line up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” 
> without
> it.
 
 #1 has been my preference for a while as well, at least as a 
 starting
 point.
>>> 
>>> I should point out that with the resyntaxing of existentials to
>>> Any, the idea that Collection's existential doesn't
>>> conform to Collection becomes far less absurd than it was, so maybe 
>>> this
>>> is not so bad.
>> 
>> I think the problem is more that Any does not conform to 
>> a specific value for a type parameter T: Collection
>> 
>> What I mean by this is that `Collection` denotes a type family, a 
>> generic parameter `T: Collection` denotes a specific (though 
>> unknown) member of that type family and `Any` denotes 
>> the type family again, so there is really no point in writing 
>> Any IMO. 
>> The type family cannot conform to T because T is just one fixed 
>> member of it.
>> It conforms to itself, though, as I can write
>> let c1: Any = …
>> let c2: Any = c1
>> 
>> That’s why I think that we could just drop Any and 
>> simply write Collection.
> 
> 
> Let me expand that a bit:
> 
> Actually all this talk about existentials vs. generics or protocols 
> vs. classes has had me confused somewhat and I think there are still 
> some misconceptions present on this list sometimes, so I’ll try to 
> clear them up:
> 
> (1) misconception: protocols with associated types are somehow very 
> different from generics
> 
> I don’t think they are and I will explain why. The only difference is 
> the way the type parameters are bound: generics use explicit 
> parameter lists whereas protocols use inheritance. That has some 
> advantages (think long parameter lists of generics) and some 
> disadvantages.
> These ways are dual in a notation sense: generic types have to have 
> all parameters bound whereas protocols cannot bind any of them.
> The „existential“ notation `Any<>` being discussed on this list is 
> nothing more than adding the ability to protocols to bind the 
> parameters to be used just like Java’s wildcards are adding the 
> opposite feature to generics, namely not having to bind all 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-12 Thread L. Mihalkovic via swift-evolution



Regards
(From mobile)
> On Jun 11, 2016, at 11:43 PM, Thorsten Seitz  wrote:
> 
> 
> 
>> Am 11.06.2016 um 15:08 schrieb L. Mihalkovic :
>> 
>> 
>>> On Jun 11, 2016, at 2:05 PM, Thorsten Seitz  wrote:
>>> 
>>> 
 Am 11.06.2016 um 12:38 schrieb L. Mihalkovic 
 :
 
 
> On Jun 11, 2016, at 11:30 AM, Thorsten Seitz  wrote:
> 
> 
>> Am 11.06.2016 um 08:00 schrieb L. Mihalkovic 
>> :
>> 
>> 
>> 
>> 
>> Regards
>> (From mobile)
>>> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>>>  wrote:
>>> 
>>> 
 Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
 :
 
 
> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
> :
> 
> 
> on Wed Jun 08 2016, Jordan Rose  wrote:
> 
>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>  wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Thorsten Seitz
>> 
>>> >> >
>>> wrote:
>>> 
 Ah, thanks, I forgot!  I still consider this a bug, though (will 
 have
 to read up again what the reasons are for that behavior).
>>> 
>>> Yes, but in the case of the issue we're discussing, the choices are:
>>> 
>>> 1. Omit from the existential's API any protocol requirements that 
>>> depend
>>> on Self or associated types, in which case it *can't* conform to
>>> itself because it doesn't fulfill the requirements.
>>> 
>>> 2. Erase type relationships and trap at runtime when they don't 
>>> line up.
>>> 
>>> Matthew has been arguing against #2, but you can't “fix the bug” 
>>> without
>>> it.
>> 
>> #1 has been my preference for a while as well, at least as a starting
>> point.
> 
> I should point out that with the resyntaxing of existentials to
> Any, the idea that Collection's existential doesn't
> conform to Collection becomes far less absurd than it was, so maybe 
> this
> is not so bad.
 
 I think the problem is more that Any does not conform to a 
 specific value for a type parameter T: Collection
 
 What I mean by this is that `Collection` denotes a type family, a 
 generic parameter `T: Collection` denotes a specific (though unknown) 
 member of that type family and `Any` denotes the type 
 family again, so there is really no point in writing Any 
 IMO. 
 The type family cannot conform to T because T is just one fixed member 
 of it.
 It conforms to itself, though, as I can write
 let c1: Any = …
 let c2: Any = c1
 
 That’s why I think that we could just drop Any and simply 
 write Collection.
>>> 
>>> 
>>> Let me expand that a bit:
>>> 
>>> Actually all this talk about existentials vs. generics or protocols vs. 
>>> classes has had me confused somewhat and I think there are still some 
>>> misconceptions present on this list sometimes, so I’ll try to clear 
>>> them up:
>>> 
>>> (1) misconception: protocols with associated types are somehow very 
>>> different from generics
>>> 
>>> I don’t think they are and I will explain why. The only difference is 
>>> the way the type parameters are bound: generics use explicit parameter 
>>> lists whereas protocols use inheritance. That has some advantages 
>>> (think long parameter lists of generics) and some disadvantages.
>>> These ways are dual in a notation sense: generic types have to have all 
>>> parameters bound whereas protocols cannot bind any of them.
>>> The „existential“ notation `Any<>` being discussed on this list is 
>>> nothing more than adding the ability to protocols to bind the 
>>> parameters to be used just like Java’s wildcards are adding the 
>>> opposite feature to generics, namely not having to bind all parameters.
>> 
>> btw, i tried to to see if Any<> could have a simpler alternative
>> https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef
> 
> As you know I like using `&` as type intersection operator. But you write 
> "The syntax leave a void when it comes to expressing the so called Top 
> type:“
> Why? Just give the top type a name, e.g. `Any` and you are done.
 Yes.. I just don't like magic. I think that all 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Thorsten Seitz via swift-evolution


> Am 11.06.2016 um 15:08 schrieb L. Mihalkovic :
> 
> 
>> On Jun 11, 2016, at 2:05 PM, Thorsten Seitz  wrote:
>> 
>> 
>>> Am 11.06.2016 um 12:38 schrieb L. Mihalkovic :
>>> 
>>> 
 On Jun 11, 2016, at 11:30 AM, Thorsten Seitz  wrote:
 
 
> Am 11.06.2016 um 08:00 schrieb L. Mihalkovic 
> :
> 
> 
> 
> 
> Regards
> (From mobile)
>> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>>  wrote:
>> 
>> 
>>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>>> :
>>> 
>>> 
 Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
 :
 
 
 on Wed Jun 08 2016, Jordan Rose  wrote:
 
>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz
> 
>> > >
>> wrote:
>> 
>>> Ah, thanks, I forgot!  I still consider this a bug, though (will 
>>> have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices are:
>> 
>> 1. Omit from the existential's API any protocol requirements that 
>> depend
>> on Self or associated types, in which case it *can't* conform to
>> itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't line 
>> up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” 
>> without
>> it.
> 
> #1 has been my preference for a while as well, at least as a starting
> point.
 
 I should point out that with the resyntaxing of existentials to
 Any, the idea that Collection's existential doesn't
 conform to Collection becomes far less absurd than it was, so maybe 
 this
 is not so bad.
>>> 
>>> I think the problem is more that Any does not conform to a 
>>> specific value for a type parameter T: Collection
>>> 
>>> What I mean by this is that `Collection` denotes a type family, a 
>>> generic parameter `T: Collection` denotes a specific (though unknown) 
>>> member of that type family and `Any` denotes the type 
>>> family again, so there is really no point in writing Any 
>>> IMO. 
>>> The type family cannot conform to T because T is just one fixed member 
>>> of it.
>>> It conforms to itself, though, as I can write
>>> let c1: Any = …
>>> let c2: Any = c1
>>> 
>>> That’s why I think that we could just drop Any and simply 
>>> write Collection.
>> 
>> 
>> Let me expand that a bit:
>> 
>> Actually all this talk about existentials vs. generics or protocols vs. 
>> classes has had me confused somewhat and I think there are still some 
>> misconceptions present on this list sometimes, so I’ll try to clear them 
>> up:
>> 
>> (1) misconception: protocols with associated types are somehow very 
>> different from generics
>> 
>> I don’t think they are and I will explain why. The only difference is 
>> the way the type parameters are bound: generics use explicit parameter 
>> lists whereas protocols use inheritance. That has some advantages (think 
>> long parameter lists of generics) and some disadvantages.
>> These ways are dual in a notation sense: generic types have to have all 
>> parameters bound whereas protocols cannot bind any of them.
>> The „existential“ notation `Any<>` being discussed on this list is 
>> nothing more than adding the ability to protocols to bind the parameters 
>> to be used just like Java’s wildcards are adding the opposite feature to 
>> generics, namely not having to bind all parameters.
> 
> btw, i tried to to see if Any<> could have a simpler alternative
> https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef
 
 As you know I like using `&` as type intersection operator. But you write 
 "The syntax leave a void when it comes to expressing the so called Top 
 type:“
 Why? Just give the top type a name, e.g. `Any` and you are done.
>>> Yes.. I just don't like magic. I think that all types should be expressable 
>>> with a syntax and that you can then decide to alias one parsing case with a 
>>> specific name. Not the other way around.
>> 
>> Well, I think that would be backwards, because we have a nominal type 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Thorsten Seitz via swift-evolution


> Am 11.06.2016 um 14:44 schrieb Matthew Johnson :
> 
> 
> 
> Sent from my iPad
> 
>> On Jun 11, 2016, at 7:31 AM, Thorsten Seitz via swift-evolution 
>>  wrote:
>> 
>> 
 Am 11.06.2016 um 14:23 schrieb Brent Royal-Gordon :
 
 The only magic would be that all type definitions (`protocol` etc.) which 
 do not give a supertype they conform to, will implicitly conform to `Any`, 
 i.e.
 
 protocol Foo { … }
 
 means
 
 protocol Foo : Any { … }
>>> 
>>> Any is also the supertype of all structural types, and structural types 
>>> cannot conform to protocols.
>> 
>> AFAIK Swift does not support structural types and I am not sure whether we 
>> should change that. In that case `Any` would become magic, yes.
> 
> Functions and tuples are structural types, although it is probably possible 
> to make tuples syntactic sugar for a Tuple type of we get the necessary 
> variadic generics support.

That's right, I forgot about them. Still I'd prefer the magic of having on type 
being the top type to having some syntax which does not work for structural 
types either and derive a top type from it.

-Thorsten 

> 
>> 
>> -Thorsten
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread L Mihalkovic via swift-evolution

> On Jun 11, 2016, at 8:46 PM, Brent Royal-Gordon  
> wrote:
> 
>>> That's certainly a valid question.  I have been very vocally skeptical
>>> that HKTs like Monad belong in the standard library, but I am not
>>> opposed to having the language feature if it supports important use
>>> cases.
>> 
>> It is surprising to see people debating the place of monads in Swift when 
>> nobody seems to speak about the elephant in the middle of the room: the 
>> language has a real engineering defisciency if it is possible for people to 
>> think that there is no better way to use it than to do   "we have around 50+ 
>> packages. This list grows very fast" (http://docs.zewo.io - many more swift 
>> github projects are equally struggling to get the code organized).
>> At the moment the only thing preventing the situation from getting more out 
>> of hands is that the import mechanism currently gets in the way, but the 
>> only opinions I read so far all focussed on making it even easier to slap 
>> things together ala zewo rather than address the engineering issue.
> 
> It would be helpful if you could do two things:
> 
> 1. Be clear about exactly what you think is wrong and, preferably, how you 
> think we might be able to solve it, or at least what sorts of problems you 
> want the solution to address. Reading this post, I'm not sure what you find 
> objectionable about this project containing 50 packages or what "situation" 
> you think is getting out of hand. Even if you have a good point, you're not 
> making it very well.

I am assuming that you have been doing professional software development for a 
long time, worked with 10s of developers in dozens of teams, using objc, swift, 
and many more languages. I think it is safe to assume you spent a great deal of 
time reading the compiler (and llvm's) source code since it became open source, 
and considering how regularly you refer to what others need or use, I also took 
for granted that you have read the code for a great deal of open-source 
projects in all sorts of languages. Having assumed this as your background, you 
might appreciate why I thought we might be able to skip of few steps.

> 
> 2. Post about your issue in a new thread rather than trying to derail 
> something *entirely* unrelated to it. I'm not sure exactly what your 
> complaint is, but I gather it has something to do with package management, 
> modules, or imports. None of these have anything to do with higher-kinded 
> types, the type system, or (as far as I can tell) anything that has ever been 
> discussed in this thread. The result is rather like interrupting a charity 
> drive for the local children's hospital to tell people that actually, they 
> really *ought* to be donating to your mosquito-net charity instead. Even if 
> you're correct that your cause is more important, it's inappropriate, 
> unwelcome, and frankly just rude.

I can appreciate your view. And maybe you can equally appreciate how plain 
surreal parts of this thread and a few others might appear when put in 
perspective with some of what I, undoubtedly
wrongly, perceive as elephants in the room. 


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Brent Royal-Gordon via swift-evolution
>> That's certainly a valid question.  I have been very vocally skeptical
>> that HKTs like Monad belong in the standard library, but I am not
>> opposed to having the language feature if it supports important use
>> cases.
> 
> It is surprising to see people debating the place of monads in Swift when 
> nobody seems to speak about the elephant in the middle of the room: the 
> language has a real engineering defisciency if it is possible for people to 
> think that there is no better way to use it than to do   "we have around 50+ 
> packages. This list grows very fast" (http://docs.zewo.io - many more swift 
> github projects are equally struggling to get the code organized).
> At the moment the only thing preventing the situation from getting more out 
> of hands is that the import mechanism currently gets in the way, but the only 
> opinions I read so far all focussed on making it even easier to slap things 
> together ala zewo rather than address the engineering issue.

It would be helpful if you could do two things:

1. Be clear about exactly what you think is wrong and, preferably, how you 
think we might be able to solve it, or at least what sorts of problems you want 
the solution to address. Reading this post, I'm not sure what you find 
objectionable about this project containing 50 packages or what "situation" you 
think is getting out of hand. Even if you have a good point, you're not making 
it very well.

2. Post about your issue in a new thread rather than trying to derail something 
*entirely* unrelated to it. I'm not sure exactly what your complaint is, but I 
gather it has something to do with package management, modules, or imports. 
None of these have anything to do with higher-kinded types, the type system, or 
(as far as I can tell) anything that has ever been discussed in this thread. 
The result is rather like interrupting a charity drive for the local children's 
hospital to tell people that actually, they really *ought* to be donating to 
your mosquito-net charity instead. Even if you're correct that your cause is 
more important, it's inappropriate, unwelcome, and frankly just rude.

In short: Please don't do this. It does not help your case.

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread L. Mihalkovic via swift-evolution
>> 
>> Of course not.  The only official plan of record for Swift is approved
>> proposals.  But it’s always interesting to know the opinions of the
>> core team about potential features.  Previously my impression had been
>> that the general leaning was towards skepticism that the practical
>> benefits of HKT would pay for the complexity.  
> 
> That's certainly a valid question.  I have been very vocally skeptical
> that HKTs like Monad belong in the standard library, but I am not
> opposed to having the language feature if it supports important use
> cases.

It is surprising to see people debating the place of monads in Swift when 
nobody seems to speak about the elephant in the middle of the room: the 
language has a real engineering defisciency if it is possible for people to 
think that there is no better way to use it than to do   "we have around 50+ 
packages. This list grows very fast" (http://docs.zewo.io - many more swift 
github projects are equally struggling to get the code organized).
At the moment the only thing preventing the situation from getting more out of 
hands is that the import mechanism currently gets in the way, but the only 
opinions I read so far all focussed on making it even easier to slap things 
together ala zewo rather than address the engineering issue.

> 
> -- 
> Dave
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread L. Mihalkovic via swift-evolution

> On Jun 11, 2016, at 3:03 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> 
> 
> Sent from my iPad
> 
>> On Jun 10, 2016, at 7:46 PM, Dave Abrahams via swift-evolution 
>>  wrote:
>> 
>> 
>> on Thu Jun 09 2016, Matthew Johnson 
>>  wrote:
>> 
 On Jun 9, 2016, at 3:05 PM, Dave Abrahams 
  wrote:
 
 
 on Thu Jun 09 2016, Matthew Johnson  wrote:
>>> 
>> On Jun 9, 2016, at 11:42 AM, Dave Abrahams 
>>  wrote:
>> 
>> 
>> on Thu Jun 09 2016, Matthew Johnson > > wrote:
> 
 On Jun 9, 2016, at 9:55 AM, Dave Abrahams
 >
 wrote:
 
 
 on Wed Jun 08 2016, Matthew Johnson >>> 
 >> wrote:
>>> 
>> On Jun 8, 2016, at 1:33 PM, Dave Abrahams
>> > >
>> wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > > wrote:
> 
 On Jun 7, 2016, at 9:15 PM, Dave Abrahams
 >
 wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson >>> 
 >> wrote:
>>> 
>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via
>> swift-evolution 
>> > >
>>  wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson
>> > >
>> wrote:
> 
 , but haven't realized
 that if you step around the type relationships encoded in Self
 requirements and associated types you end up with types that 
 appear to
 interoperate but in fact trap at runtime unless used in 
 exactly the
 right way.
>>> 
>>> Trap at runtime?  How so?  Generalized existentials should 
>>> still be
>>> type-safe.  
>> 
>> There are two choices when you erase static type relationships:
>> 
>> 1. Acheive type-safety by trapping at runtime
>> 
>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // 
>> trap
>> 
>> 2. Don't expose protocol requirements that involve these 
>> relationships,
>> which would prevent the code above from compiling and prevent
>> FloatingPoint from conforming to itself.
>> 
>>> Or are you talking about the hypothetical types / behaviors 
>>> people
>>> think they want when they don’t fully understand what is 
>>> happening...
>> 
>> I don't know what you mean here.  I think generalized 
>> existentials will
>> be nice to have, but I think most people will want them to do 
>> something
>> they can't possibly do.
> 
> Exactly.  What I meant is that people think they want that 
> expression
> to compile because they don’t understand that the only thing it 
> can do
> is trap.  I said “hypothetical” because producing a compile time 
> error
> rather than a runtime trap is the only sane thing to do.  Your 
> comment
> surprised me because I can’t imagine we would move forward in 
> Swift
> with the approach of trapping.
 
 I would very much like to be able to create instances of 
 “Collection
 where Element == Int” so we can throw away the wrappers in the 
 stdlib.
 That will require some type mismatches to be caught at runtime via
 trapping.
>>> 
>>> For invalid index because the existential accepts a type erased 
>>> index?
>> 
>> Exactly.
>> 
>>> How do you decide where to draw the line here?  It feels like a very
>>> slippery slope for a language where safety is a 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

On Jun 11, 2016, at 7:48 AM, Brent Royal-Gordon  wrote:

>> Functions and tuples are structural types, although it is probably possible 
>> to make tuples syntactic sugar for a Tuple type of we get the necessary 
>> variadic generics support.
> 
> The design the variadic generics thread seems to have preliminarily settled 
> on is based on representing variadic generics as tuples, so I imagine we 
> would hit some issues with circularity!

I'm not sure this topic is settled at all (felt a bit more like deferred I 
thought).  But this may well turn out to be the case.  There is some 
circularity either way of course - one will probably be defined in terms of the 
other.

The more important point is that Swift does have structural types and even if 
you could define Tuple with variadic generics you still have structural 
function types.  So it will always have at least one structural type.

> 
> -- 
> Brent Royal-Gordon
> Architechies
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread L. Mihalkovic via swift-evolution


> On Jun 11, 2016, at 2:31 PM, Thorsten Seitz  wrote:
> 
> 
>>> Am 11.06.2016 um 14:23 schrieb Brent Royal-Gordon :
>>> 
>>> The only magic would be that all type definitions (`protocol` etc.) which 
>>> do not give a supertype they conform to, will implicitly conform to `Any`, 
>>> i.e.
>>> 
>>> protocol Foo { … }
>>> 
>>> means
>>> 
>>> protocol Foo : Any { … }
>> 
>> Any is also the supertype of all structural types, and structural types 
>> cannot conform to protocols.
> 
> AFAIK Swift does not support structural types and I am not sure whether we 
> should change that. In that case `Any` would become magic, yes.

Hmmm poor tuples... I thought they did a good job as swift's structural type.


> 
> -Thorsten
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread L. Mihalkovic via swift-evolution

> On Jun 11, 2016, at 2:05 PM, Thorsten Seitz  wrote:
> 
> 
>> Am 11.06.2016 um 12:38 schrieb L. Mihalkovic :
>> 
>> 
>>> On Jun 11, 2016, at 11:30 AM, Thorsten Seitz  wrote:
>>> 
>>> 
 Am 11.06.2016 um 08:00 schrieb L. Mihalkovic 
 :
 
 
 
 
 Regards
 (From mobile)
> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>> :
>> 
>> 
>>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>>> :
>>> 
>>> 
>>> on Wed Jun 08 2016, Jordan Rose  wrote:
>>> 
> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>  wrote:
> 
> 
> on Wed Jun 08 2016, Thorsten Seitz
 
>  >
> wrote:
> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices are:
> 
> 1. Omit from the existential's API any protocol requirements that 
> depend
> on Self or associated types, in which case it *can't* conform to
> itself because it doesn't fulfill the requirements.
> 
> 2. Erase type relationships and trap at runtime when they don't line 
> up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” 
> without
> it.
 
 #1 has been my preference for a while as well, at least as a starting
 point.
>>> 
>>> I should point out that with the resyntaxing of existentials to
>>> Any, the idea that Collection's existential doesn't
>>> conform to Collection becomes far less absurd than it was, so maybe this
>>> is not so bad.
>> 
>> I think the problem is more that Any does not conform to a 
>> specific value for a type parameter T: Collection
>> 
>> What I mean by this is that `Collection` denotes a type family, a 
>> generic parameter `T: Collection` denotes a specific (though unknown) 
>> member of that type family and `Any` denotes the type family 
>> again, so there is really no point in writing Any IMO. 
>> The type family cannot conform to T because T is just one fixed member 
>> of it.
>> It conforms to itself, though, as I can write
>> let c1: Any = …
>> let c2: Any = c1
>> 
>> That’s why I think that we could just drop Any and simply 
>> write Collection.
> 
> 
> Let me expand that a bit:
> 
> Actually all this talk about existentials vs. generics or protocols vs. 
> classes has had me confused somewhat and I think there are still some 
> misconceptions present on this list sometimes, so I’ll try to clear them 
> up:
> 
> (1) misconception: protocols with associated types are somehow very 
> different from generics
> 
> I don’t think they are and I will explain why. The only difference is the 
> way the type parameters are bound: generics use explicit parameter lists 
> whereas protocols use inheritance. That has some advantages (think long 
> parameter lists of generics) and some disadvantages.
> These ways are dual in a notation sense: generic types have to have all 
> parameters bound whereas protocols cannot bind any of them.
> The „existential“ notation `Any<>` being discussed on this list is 
> nothing more than adding the ability to protocols to bind the parameters 
> to be used just like Java’s wildcards are adding the opposite feature to 
> generics, namely not having to bind all parameters.
 
 btw, i tried to to see if Any<> could have a simpler alternative
 https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef
>>> 
>>> As you know I like using `&` as type intersection operator. But you write 
>>> "The syntax leave a void when it comes to expressing the so called Top 
>>> type:“
>>> Why? Just give the top type a name, e.g. `Any` and you are done.
>> Yes.. I just don't like magic. I think that all types should be expressable 
>> with a syntax and that you can then decide to alias one parsing case with a 
>> specific name. Not the other way around.
> 
> Well, I think that would be backwards, because we have a nominal type system. 
> That means that the syntax for a type is just its name. 

I realize we do not understand each other. 
The words we use now to describe a behavior are just that, words. As is the 
concepts they describe are useless to the 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jun 10, 2016, at 7:46 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Thu Jun 09 2016, Matthew Johnson 
>  wrote:
> 
>>> On Jun 9, 2016, at 3:05 PM, Dave Abrahams 
>>>  wrote:
>>> 
>>> 
>>> on Thu Jun 09 2016, Matthew Johnson  wrote:
>> 
> On Jun 9, 2016, at 11:42 AM, Dave Abrahams 
>  wrote:
> 
> 
> on Thu Jun 09 2016, Matthew Johnson  > wrote:
 
>>> On Jun 9, 2016, at 9:55 AM, Dave Abrahams
>>> >> >
>>> wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Matthew Johnson >> 
>>> >> >> wrote:
>> 
> On Jun 8, 2016, at 1:33 PM, Dave Abrahams
>  >
> wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  > wrote:
 
>>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams
>>> >> >
>>> wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson >> 
>>> >> >> wrote:
>> 
> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via
> swift-evolution 
>  > 
> wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson
>  >
> wrote:
 
>>> , but haven't realized
>>> that if you step around the type relationships encoded in Self
>>> requirements and associated types you end up with types that 
>>> appear to
>>> interoperate but in fact trap at runtime unless used in exactly 
>>> the
>>> right way.
>> 
>> Trap at runtime?  How so?  Generalized existentials should still 
>> be
>> type-safe.  
> 
> There are two choices when you erase static type relationships:
> 
> 1. Acheive type-safety by trapping at runtime
> 
> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
> 
> 2. Don't expose protocol requirements that involve these 
> relationships,
> which would prevent the code above from compiling and prevent
> FloatingPoint from conforming to itself.
> 
>> Or are you talking about the hypothetical types / behaviors 
>> people
>> think they want when they don’t fully understand what is 
>> happening...
> 
> I don't know what you mean here.  I think generalized 
> existentials will
> be nice to have, but I think most people will want them to do 
> something
> they can't possibly do.
 
 Exactly.  What I meant is that people think they want that 
 expression
 to compile because they don’t understand that the only thing it 
 can do
 is trap.  I said “hypothetical” because producing a compile time 
 error
 rather than a runtime trap is the only sane thing to do.  Your 
 comment
 surprised me because I can’t imagine we would move forward in Swift
 with the approach of trapping.
>>> 
>>> I would very much like to be able to create instances of “Collection
>>> where Element == Int” so we can throw away the wrappers in the 
>>> stdlib.
>>> That will require some type mismatches to be caught at runtime via
>>> trapping.
>> 
>> For invalid index because the existential accepts a type erased 
>> index?
> 
> Exactly.
> 
>> How do you decide where to draw the line here?  It feels like a very
>> slippery slope for a language where safety is a stated priority to
>> start adopting a strategy of runtime trapping for something as
>> fundamental as how you expose members on an existential.
> 
> If you don't do this, the alternative is that “Collection where 
> Element
> == Int” 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Brent Royal-Gordon via swift-evolution
> Functions and tuples are structural types, although it is probably possible 
> to make tuples syntactic sugar for a Tuple type of we get the necessary 
> variadic generics support.

The design the variadic generics thread seems to have preliminarily settled on 
is based on representing variadic generics as tuples, so I imagine we would hit 
some issues with circularity!

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Jonathan Hull via swift-evolution
Yikes!  I had intended to call rhs._value in ==.  Thank you :-)  You saved me a 
lot of debugging time.  I ended up fixing with your version.

You can see why I would love to have Swift do the thunk-ing for me… less 
opportunity to shoot myself in the foot with Any.

Thanks,
Jon

> On Jun 11, 2016, at 5:25 AM, Thorsten Seitz  wrote:
> 
>> 
>> Am 11.06.2016 um 13:22 schrieb Jonathan Hull via swift-evolution 
>> >:
>> 
>> Here is another example from a current project: (Here there is an option to 
>> trap, if desired… but many more options not to)
>> (Note: The commented out bit was an attempt to get the compiler to play 
>> nicer with intuiting the type, but it didn’t help… leaving as data)
>> 
>> struct HashableBox:Hashable {
>> private let _value:Any
>> private let _hash:Int
>> private let _eq:(Any)->Bool
>> 
>> enum Error:ErrorType {
>> case typeMismatch
>> }
>> 
>> init(_ value:T){
>> self._value = value
>> self._hash = value.hashValue
>> self._eq = { other in
>> guard let otherT = other as? T else {return false}
>> return value == otherT
>> }
>> }
> 
> I think there is an error in the implementation of _eq, because it should try 
> to unpack the value as T and not the box.
> 
> HashableBox(1) == HashableBox(1) should be true IMO but is false with your 
> implementation
> 
> This works as I would expect:
> 
> private let _eq:(HashableBox)->Bool
> 
> init(_ value:T){
> self._value = value
> self._hash = value.hashValue
> self._eq = { other in
> guard let otherValue: T = other.valueOrNil() else { return false }
> return value == otherValue
> }
> }
> 
> -Thorsten
> 
> 
>> 
>> func valueOrCrash(msg:String? = nil) -> T {
>> guard let value = _value as? T else {
>> let msg = msg ?? "Attempt to retrieve value of type 
>> \(self._value.dynamicType) as \(T.self)"
>> fatalError(msg)
>> }
>> return value
>> }
>> 
>> func valueOrNil() -> T? {//(type:T.Type = T.self) -> T? {
>> return self._value as? T
>> }
>> 
>> func valueOrError()throws -> T {
>> guard let value = _value as? T else {throw Error.typeMismatch}
>> return value
>> }
>> 
>> var asAny:Any {
>> return _value
>> }
>> 
>> var hashValue: Int {
>> return _hash
>> }
>> }
>> 
>> func == (lhs:HashableBox, rhs:HashableBox) -> Bool {
>> return lhs._eq(rhs)
>> }
>> 
>> 
>> Thanks,
>> Jon
>> 
>>> On Jun 11, 2016, at 3:25 AM, Jonathan Hull >> > wrote:
>>> 
>>> 
 If your code has many manual type erasing wrappers corresponding to
 protocols with associated types and/or Self requirements that also never
 have to trap type mismatches, that would certainly be instructive
 empirical data.  Would you care to share the protocols and wrappers you
 are talking about?
>>> This code is a bit embarrassing (I wrote most of it as I was still learning 
>>> Swift), but if it is helpful I will share:
>>> https://gist.github.com/jonhull/639e756ad5228348f93f40f06169588c 
>>> 
>>> 
>>> It doesn’t trap anywhere (that I know about). Some of the code which calls 
>>> it does throw an error in the case of mismatched types (but it 
>>> doesn’t/shouldn't crash).  Most functions which use it are generic on the 
>>> associatedType.
>>> 
>>> It does work fairly well though (even on the AppleWatch).  The main issue 
>>> is that I have no way to persist the values which have been drawn into the 
>>> type-erased world (or even the value-type world, really).
>>> 
>>> Also, if anyone has a better way to write the type erasing wrapper, I would 
>>> love to hear it. These are very memory intensive…
>>> 
>>> Thanks,
>>> Jon
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jun 11, 2016, at 7:31 AM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
>>> Am 11.06.2016 um 14:23 schrieb Brent Royal-Gordon :
>>> 
>>> The only magic would be that all type definitions (`protocol` etc.) which 
>>> do not give a supertype they conform to, will implicitly conform to `Any`, 
>>> i.e.
>>> 
>>> protocol Foo { … }
>>> 
>>> means
>>> 
>>> protocol Foo : Any { … }
>> 
>> Any is also the supertype of all structural types, and structural types 
>> cannot conform to protocols.
> 
> AFAIK Swift does not support structural types and I am not sure whether we 
> should change that. In that case `Any` would become magic, yes.

Functions and tuples are structural types, although it is probably possible to 
make tuples syntactic sugar for a Tuple type of we get the necessary variadic 
generics support.

> 
> -Thorsten
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Thorsten Seitz via swift-evolution

> Am 11.06.2016 um 14:23 schrieb Brent Royal-Gordon :
> 
>> The only magic would be that all type definitions (`protocol` etc.) which do 
>> not give a supertype they conform to, will implicitly conform to `Any`, i.e.
>> 
>> protocol Foo { … }
>> 
>> means
>> 
>> protocol Foo : Any { … }
> 
> Any is also the supertype of all structural types, and structural types 
> cannot conform to protocols.

AFAIK Swift does not support structural types and I am not sure whether we 
should change that. In that case `Any` would become magic, yes.

-Thorsten
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Thorsten Seitz via swift-evolution

> Am 11.06.2016 um 13:22 schrieb Jonathan Hull via swift-evolution 
> :
> 
> Here is another example from a current project: (Here there is an option to 
> trap, if desired… but many more options not to)
> (Note: The commented out bit was an attempt to get the compiler to play nicer 
> with intuiting the type, but it didn’t help… leaving as data)
> 
> struct HashableBox:Hashable {
> private let _value:Any
> private let _hash:Int
> private let _eq:(Any)->Bool
> 
> enum Error:ErrorType {
> case typeMismatch
> }
> 
> init(_ value:T){
> self._value = value
> self._hash = value.hashValue
> self._eq = { other in
> guard let otherT = other as? T else {return false}
> return value == otherT
> }
> }

I think there is an error in the implementation of _eq, because it should try 
to unpack the value as T and not the box.

HashableBox(1) == HashableBox(1) should be true IMO but is false with your 
implementation

This works as I would expect:

private let _eq:(HashableBox)->Bool

init(_ value:T){
self._value = value
self._hash = value.hashValue
self._eq = { other in
guard let otherValue: T = other.valueOrNil() else { return false }
return value == otherValue
}
}

-Thorsten


> 
> func valueOrCrash(msg:String? = nil) -> T {
> guard let value = _value as? T else {
> let msg = msg ?? "Attempt to retrieve value of type 
> \(self._value.dynamicType) as \(T.self)"
> fatalError(msg)
> }
> return value
> }
> 
> func valueOrNil() -> T? {//(type:T.Type = T.self) -> T? {
> return self._value as? T
> }
> 
> func valueOrError()throws -> T {
> guard let value = _value as? T else {throw Error.typeMismatch}
> return value
> }
> 
> var asAny:Any {
> return _value
> }
> 
> var hashValue: Int {
> return _hash
> }
> }
> 
> func == (lhs:HashableBox, rhs:HashableBox) -> Bool {
> return lhs._eq(rhs)
> }
> 
> 
> Thanks,
> Jon
> 
>> On Jun 11, 2016, at 3:25 AM, Jonathan Hull > > wrote:
>> 
>> 
>>> If your code has many manual type erasing wrappers corresponding to
>>> protocols with associated types and/or Self requirements that also never
>>> have to trap type mismatches, that would certainly be instructive
>>> empirical data.  Would you care to share the protocols and wrappers you
>>> are talking about?
>> This code is a bit embarrassing (I wrote most of it as I was still learning 
>> Swift), but if it is helpful I will share:
>> https://gist.github.com/jonhull/639e756ad5228348f93f40f06169588c 
>> 
>> 
>> It doesn’t trap anywhere (that I know about). Some of the code which calls 
>> it does throw an error in the case of mismatched types (but it 
>> doesn’t/shouldn't crash).  Most functions which use it are generic on the 
>> associatedType.
>> 
>> It does work fairly well though (even on the AppleWatch).  The main issue is 
>> that I have no way to persist the values which have been drawn into the 
>> type-erased world (or even the value-type world, really).
>> 
>> Also, if anyone has a better way to write the type erasing wrapper, I would 
>> love to hear it. These are very memory intensive…
>> 
>> Thanks,
>> Jon
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Brent Royal-Gordon via swift-evolution
> The only magic would be that all type definitions (`protocol` etc.) which do 
> not give a supertype they conform to, will implicitly conform to `Any`, i.e.
> 
> protocol Foo { … }
> 
> means
> 
> protocol Foo : Any { … }

Any is also the supertype of all structural types, and structural types cannot 
conform to protocols.

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Thorsten Seitz via swift-evolution

> Am 11.06.2016 um 12:38 schrieb L. Mihalkovic :
> 
> 
>> On Jun 11, 2016, at 11:30 AM, Thorsten Seitz  wrote:
>> 
>> 
>>> Am 11.06.2016 um 08:00 schrieb L. Mihalkovic :
>>> 
>>> 
>>> 
>>> 
>>> Regards
>>> (From mobile)
 On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
  wrote:
 
 
> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
> :
> 
> 
>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>> :
>> 
>> 
>> on Wed Jun 08 2016, Jordan Rose  wrote:
>> 
 On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
  wrote:
 
 
 on Wed Jun 08 2016, Thorsten Seitz
>>> 
 >
 wrote:
 
> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> to read up again what the reasons are for that behavior).
 
 Yes, but in the case of the issue we're discussing, the choices are:
 
 1. Omit from the existential's API any protocol requirements that 
 depend
 on Self or associated types, in which case it *can't* conform to
 itself because it doesn't fulfill the requirements.
 
 2. Erase type relationships and trap at runtime when they don't line 
 up.
 
 Matthew has been arguing against #2, but you can't “fix the bug” 
 without
 it.
>>> 
>>> #1 has been my preference for a while as well, at least as a starting
>>> point.
>> 
>> I should point out that with the resyntaxing of existentials to
>> Any, the idea that Collection's existential doesn't
>> conform to Collection becomes far less absurd than it was, so maybe this
>> is not so bad.
> 
> I think the problem is more that Any does not conform to a 
> specific value for a type parameter T: Collection
> 
> What I mean by this is that `Collection` denotes a type family, a generic 
> parameter `T: Collection` denotes a specific (though unknown) member of 
> that type family and `Any` denotes the type family again, so 
> there is really no point in writing Any IMO. 
> The type family cannot conform to T because T is just one fixed member of 
> it.
> It conforms to itself, though, as I can write
> let c1: Any = …
> let c2: Any = c1
> 
> That’s why I think that we could just drop Any and simply 
> write Collection.
 
 
 Let me expand that a bit:
 
 Actually all this talk about existentials vs. generics or protocols vs. 
 classes has had me confused somewhat and I think there are still some 
 misconceptions present on this list sometimes, so I’ll try to clear them 
 up:
 
 (1) misconception: protocols with associated types are somehow very 
 different from generics
 
 I don’t think they are and I will explain why. The only difference is the 
 way the type parameters are bound: generics use explicit parameter lists 
 whereas protocols use inheritance. That has some advantages (think long 
 parameter lists of generics) and some disadvantages.
 These ways are dual in a notation sense: generic types have to have all 
 parameters bound whereas protocols cannot bind any of them.
 The „existential“ notation `Any<>` being discussed on this list is nothing 
 more than adding the ability to protocols to bind the parameters to be 
 used just like Java’s wildcards are adding the opposite feature to 
 generics, namely not having to bind all parameters.
>>> 
>>> btw, i tried to to see if Any<> could have a simpler alternative
>>> https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef
>> 
>> As you know I like using `&` as type intersection operator. But you write 
>> "The syntax leave a void when it comes to expressing the so called Top type:“
>> Why? Just give the top type a name, e.g. `Any` and you are done.
> Yes.. I just don't like magic. I think that all types should be expressable 
> with a syntax and that you can then decide to alias one parsing case with a 
> specific name. Not the other way around.

Well, I think that would be backwards, because we have a nominal type system. 
That means that the syntax for a type is just its name. 
`&` is a type operator which creates a new type from its operands.
`where` clauses add constraints to types.
But it all starts with a type's name.

The only magic would be that all type definitions (`protocol` etc.) which do 
not give a supertype they conform to, will implicitly conform to `Any`, i.e.

protocol Foo { … }

means

protocol Foo : Any { … }

That’s less 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Jonathan Hull via swift-evolution
Here is another example from a current project: (Here there is an option to 
trap, if desired… but many more options not to)
(Note: The commented out bit was an attempt to get the compiler to play nicer 
with intuiting the type, but it didn’t help… leaving as data)

struct HashableBox:Hashable {
private let _value:Any
private let _hash:Int
private let _eq:(Any)->Bool

enum Error:ErrorType {
case typeMismatch
}

init(_ value:T){
self._value = value
self._hash = value.hashValue
self._eq = { other in
guard let otherT = other as? T else {return false}
return value == otherT
}
}

func valueOrCrash(msg:String? = nil) -> T {
guard let value = _value as? T else {
let msg = msg ?? "Attempt to retrieve value of type 
\(self._value.dynamicType) as \(T.self)"
fatalError(msg)
}
return value
}

func valueOrNil() -> T? {//(type:T.Type = T.self) -> T? {
return self._value as? T
}

func valueOrError()throws -> T {
guard let value = _value as? T else {throw Error.typeMismatch}
return value
}

var asAny:Any {
return _value
}

var hashValue: Int {
return _hash
}
}

func == (lhs:HashableBox, rhs:HashableBox) -> Bool {
return lhs._eq(rhs)
}


Thanks,
Jon

> On Jun 11, 2016, at 3:25 AM, Jonathan Hull  wrote:
> 
> 
>> If your code has many manual type erasing wrappers corresponding to
>> protocols with associated types and/or Self requirements that also never
>> have to trap type mismatches, that would certainly be instructive
>> empirical data.  Would you care to share the protocols and wrappers you
>> are talking about?
> This code is a bit embarrassing (I wrote most of it as I was still learning 
> Swift), but if it is helpful I will share:
> https://gist.github.com/jonhull/639e756ad5228348f93f40f06169588c 
> 
> 
> It doesn’t trap anywhere (that I know about). Some of the code which calls it 
> does throw an error in the case of mismatched types (but it doesn’t/shouldn't 
> crash).  Most functions which use it are generic on the associatedType.
> 
> It does work fairly well though (even on the AppleWatch).  The main issue is 
> that I have no way to persist the values which have been drawn into the 
> type-erased world (or even the value-type world, really).
> 
> Also, if anyone has a better way to write the type erasing wrapper, I would 
> love to hear it. These are very memory intensive…
> 
> Thanks,
> Jon

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread L. Mihalkovic via swift-evolution

> On Jun 11, 2016, at 11:30 AM, Thorsten Seitz  wrote:
> 
> 
>> Am 11.06.2016 um 08:00 schrieb L. Mihalkovic :
>> 
>> 
>> 
>> 
>> Regards
>> (From mobile)
>>> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>>>  wrote:
>>> 
>>> 
 Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
 :
 
 
> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
> :
> 
> 
> on Wed Jun 08 2016, Jordan Rose  wrote:
> 
>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>  wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Thorsten Seitz
>> 
>>> >> >
>>> wrote:
>>> 
 Ah, thanks, I forgot!  I still consider this a bug, though (will have
 to read up again what the reasons are for that behavior).
>>> 
>>> Yes, but in the case of the issue we're discussing, the choices are:
>>> 
>>> 1. Omit from the existential's API any protocol requirements that depend
>>> on Self or associated types, in which case it *can't* conform to
>>> itself because it doesn't fulfill the requirements.
>>> 
>>> 2. Erase type relationships and trap at runtime when they don't line up.
>>> 
>>> Matthew has been arguing against #2, but you can't “fix the bug” without
>>> it.
>> 
>> #1 has been my preference for a while as well, at least as a starting
>> point.
> 
> I should point out that with the resyntaxing of existentials to
> Any, the idea that Collection's existential doesn't
> conform to Collection becomes far less absurd than it was, so maybe this
> is not so bad.
 
 I think the problem is more that Any does not conform to a 
 specific value for a type parameter T: Collection
 
 What I mean by this is that `Collection` denotes a type family, a generic 
 parameter `T: Collection` denotes a specific (though unknown) member of 
 that type family and `Any` denotes the type family again, so 
 there is really no point in writing Any IMO. 
 The type family cannot conform to T because T is just one fixed member of 
 it.
 It conforms to itself, though, as I can write
 let c1: Any = …
 let c2: Any = c1
 
 That’s why I think that we could just drop Any and simply 
 write Collection.
>>> 
>>> 
>>> Let me expand that a bit:
>>> 
>>> Actually all this talk about existentials vs. generics or protocols vs. 
>>> classes has had me confused somewhat and I think there are still some 
>>> misconceptions present on this list sometimes, so I’ll try to clear them up:
>>> 
>>> (1) misconception: protocols with associated types are somehow very 
>>> different from generics
>>> 
>>> I don’t think they are and I will explain why. The only difference is the 
>>> way the type parameters are bound: generics use explicit parameter lists 
>>> whereas protocols use inheritance. That has some advantages (think long 
>>> parameter lists of generics) and some disadvantages.
>>> These ways are dual in a notation sense: generic types have to have all 
>>> parameters bound whereas protocols cannot bind any of them.
>>> The „existential“ notation `Any<>` being discussed on this list is nothing 
>>> more than adding the ability to protocols to bind the parameters to be used 
>>> just like Java’s wildcards are adding the opposite feature to generics, 
>>> namely not having to bind all parameters.
>> 
>> btw, i tried to to see if Any<> could have a simpler alternative
>> https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef
> 
> As you know I like using `&` as type intersection operator. But you write 
> "The syntax leave a void when it comes to expressing the so called Top type:“
> Why? Just give the top type a name, e.g. `Any` and you are done.
Yes.. I just don't like magic. I think that all types should be expressable 
with a syntax and that you can then decide to alias one parsing case with a 
specific name. Not the other way around.

> Why should the top type have special *syntax*? It is just the type all other 
> types conform to. No need to do something special here and therefore no need 
> to invent an alternative syntax like `Any<>` or the alternative from your 
> gist which is rather confusing IMO (and I don’t like the special case given 
> to classes in the syntax).
The _[] case is just a degenerate case of the syntax, showing that it is 
expressible inside, as opposoed to have to define a contextual keyword (read 
the SourceKit code). And then it is aliasable. Part of the problems in swift 
today to me is that some things are no doable in swift, so the compiler must 
contain that semantic. This here is just one example, but there are others. 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Jonathan Hull via swift-evolution

> If your code has many manual type erasing wrappers corresponding to
> protocols with associated types and/or Self requirements that also never
> have to trap type mismatches, that would certainly be instructive
> empirical data.  Would you care to share the protocols and wrappers you
> are talking about?
This code is a bit embarrassing (I wrote most of it as I was still learning 
Swift), but if it is helpful I will share:
https://gist.github.com/jonhull/639e756ad5228348f93f40f06169588c

It doesn’t trap anywhere (that I know about). Some of the code which calls it 
does throw an error in the case of mismatched types (but it doesn’t/shouldn't 
crash).  Most functions which use it are generic on the associatedType.

It does work fairly well though (even on the AppleWatch).  The main issue is 
that I have no way to persist the values which have been drawn into the 
type-erased world (or even the value-type world, really).

Also, if anyone has a better way to write the type erasing wrapper, I would 
love to hear it. These are very memory intensive…

Thanks,
Jon___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread Thorsten Seitz via swift-evolution

> Am 11.06.2016 um 08:00 schrieb L. Mihalkovic :
> 
> 
> 
> 
> Regards
> (From mobile)
>> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>>  wrote:
>> 
>> 
>>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>>> :
>>> 
>>> 
 Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
 :
 
 
 on Wed Jun 08 2016, Jordan Rose  wrote:
 
>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz
> 
>> > >
>> wrote:
>> 
>>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices are:
>> 
>> 1. Omit from the existential's API any protocol requirements that depend
>> on Self or associated types, in which case it *can't* conform to
>> itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't line up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” without
>> it.
> 
> #1 has been my preference for a while as well, at least as a starting
> point.
 
 I should point out that with the resyntaxing of existentials to
 Any, the idea that Collection's existential doesn't
 conform to Collection becomes far less absurd than it was, so maybe this
 is not so bad.
>>> 
>>> I think the problem is more that Any does not conform to a 
>>> specific value for a type parameter T: Collection
>>> 
>>> What I mean by this is that `Collection` denotes a type family, a generic 
>>> parameter `T: Collection` denotes a specific (though unknown) member of 
>>> that type family and `Any` denotes the type family again, so 
>>> there is really no point in writing Any IMO. 
>>> The type family cannot conform to T because T is just one fixed member of 
>>> it.
>>> It conforms to itself, though, as I can write
>>> let c1: Any = …
>>> let c2: Any = c1
>>> 
>>> That’s why I think that we could just drop Any and simply write 
>>> Collection.
>> 
>> 
>> Let me expand that a bit:
>> 
>> Actually all this talk about existentials vs. generics or protocols vs. 
>> classes has had me confused somewhat and I think there are still some 
>> misconceptions present on this list sometimes, so I’ll try to clear them up:
>> 
>> (1) misconception: protocols with associated types are somehow very 
>> different from generics
>> 
>> I don’t think they are and I will explain why. The only difference is the 
>> way the type parameters are bound: generics use explicit parameter lists 
>> whereas protocols use inheritance. That has some advantages (think long 
>> parameter lists of generics) and some disadvantages.
>> These ways are dual in a notation sense: generic types have to have all 
>> parameters bound whereas protocols cannot bind any of them.
>> The „existential“ notation `Any<>` being discussed on this list is nothing 
>> more than adding the ability to protocols to bind the parameters to be used 
>> just like Java’s wildcards are adding the opposite feature to generics, 
>> namely not having to bind all parameters.
> 
> btw, i tried to to see if Any<> could have a simpler alternative
> https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef

As you know I like using `&` as type intersection operator. But you write "The 
syntax leave a void when it comes to expressing the so called Top type:“
Why? Just give the top type a name, e.g. `Any` and you are done. Why should the 
top type have special *syntax*? It is just the type all other types conform to. 
No need to do something special here and therefore no need to invent an 
alternative syntax like `Any<>` or the alternative from your gist which is 
rather confusing IMO (and I don’t like the special case given to classes in the 
syntax).


> 
>> Essentially `Any` in Swift is just the same as `Collection` 
>> in Java (assuming for comparability’s sake that Swift’s Collection had no 
>> additional associated types; otherwise I would just have to introduce a 
>> Collection in Java).
>> 
>> Likewise `Any` is just the same as 
>> `Collection` in Java.
> Java supports co/contra variant params

Java has no declaration-site variance like Ceylon or Scala have (see e.g. 
http://ceylon-lang.org/blog/2014/07/14/wildcards#why_i_distrust_wildcards_and_why_we_need_them_anyway).

Java’s wildcards are a way to express use-site variance. The proposed `Any<>` 
does just the same. 


> 
>> And just like Collection does not conform to a type parameter `T extends 
>> Collection` because Collection is the 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-11 Thread L. Mihalkovic via swift-evolution



Regards
(From mobile)
> On Jun 10, 2016, at 9:35 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
>> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
>> :
>> 
>> 
>>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>>> :
>>> 
>>> 
>>> on Wed Jun 08 2016, Jordan Rose  wrote:
>>> 
> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>  wrote:
> 
> 
> on Wed Jun 08 2016, Thorsten Seitz
 
>  >
> wrote:
> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices are:
> 
> 1. Omit from the existential's API any protocol requirements that depend
> on Self or associated types, in which case it *can't* conform to
> itself because it doesn't fulfill the requirements.
> 
> 2. Erase type relationships and trap at runtime when they don't line up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” without
> it.
 
 #1 has been my preference for a while as well, at least as a starting
 point.
>>> 
>>> I should point out that with the resyntaxing of existentials to
>>> Any, the idea that Collection's existential doesn't
>>> conform to Collection becomes far less absurd than it was, so maybe this
>>> is not so bad.
>> 
>> I think the problem is more that Any does not conform to a 
>> specific value for a type parameter T: Collection
>> 
>> What I mean by this is that `Collection` denotes a type family, a generic 
>> parameter `T: Collection` denotes a specific (though unknown) member of that 
>> type family and `Any` denotes the type family again, so there is 
>> really no point in writing Any IMO. 
>> The type family cannot conform to T because T is just one fixed member of it.
>> It conforms to itself, though, as I can write
>> let c1: Any = …
>> let c2: Any = c1
>> 
>> That’s why I think that we could just drop Any and simply write 
>> Collection.
> 
> 
> Let me expand that a bit:
> 
> Actually all this talk about existentials vs. generics or protocols vs. 
> classes has had me confused somewhat and I think there are still some 
> misconceptions present on this list sometimes, so I’ll try to clear them up:
> 
> (1) misconception: protocols with associated types are somehow very different 
> from generics
> 
> I don’t think they are and I will explain why. The only difference is the way 
> the type parameters are bound: generics use explicit parameter lists whereas 
> protocols use inheritance. That has some advantages (think long parameter 
> lists of generics) and some disadvantages.
> These ways are dual in a notation sense: generic types have to have all 
> parameters bound whereas protocols cannot bind any of them.
> The „existential“ notation `Any<>` being discussed on this list is nothing 
> more than adding the ability to protocols to bind the parameters to be used 
> just like Java’s wildcards are adding the opposite feature to generics, 
> namely not having to bind all parameters.

btw, i tried to to see if Any<> could have a simpler alternative
https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef

> Essentially `Any` in Swift is just the same as `Collection` in 
> Java (assuming for comparability’s sake that Swift’s Collection had no 
> additional associated types; otherwise I would just have to introduce a 
> Collection in Java).
> 
> Likewise `Any` is just the same as 
> `Collection` in Java.
Java supports co/contra variant params

> And just like Collection does not conform to a type parameter `T extends 
> Collection` because Collection is the type `forall E. Collection` 
> whereas `T extends Collection` is the type `T. Collection` for a given 
> T.

This picture is accurate today, but there are going to be more serious 
differences after 10 no date is currently geven for when it will come)

> In essence protocols with associated types are like generics with wildcards.

Yes, java has kept everything within its generics system rather than split 
parts out. Something people may not immediately think about iwith respect to 
the 2 generic systems is that when u call a funccapture(T t){}  in java with 
a wildcard you are doing a compile time capture only (to avoid the dreaded 
unsafe casts), whereas it is really nice to do the same in swift and 
subsequently be able to access T.Type and see that it is not Any. The closest u 
ever get to that type at runtime in java is via generics introspection, but u 
still can't do everything ( like no new T() ). But today the bridging between 
existential types and generics is definitely a work in progress.

> Coming back to the 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-10 Thread Dave Abrahams via swift-evolution

on Thu Jun 09 2016, Matthew Johnson 
 wrote:

>> On Jun 9, 2016, at 3:05 PM, Dave Abrahams 
>>  wrote:
>> 
>> 
>> on Thu Jun 09 2016, Matthew Johnson  wrote:
>> 
>
 On Jun 9, 2016, at 11:42 AM, Dave Abrahams 
  wrote:
 
 
 on Thu Jun 09 2016, Matthew Johnson >>> > wrote:
 
>>> 
>> On Jun 9, 2016, at 9:55 AM, Dave Abrahams
>> > >
>> wrote:
>> 
>> 
>> on Wed Jun 08 2016, Matthew Johnson > 
>> > >> wrote:
>> 
> 
 On Jun 8, 2016, at 1:33 PM, Dave Abrahams
 >
 wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson >>> > wrote:
 
>>> 
>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams
>> > >
>> wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > 
>> > >> wrote:
>> 
> 
 On Jun 7, 2016, at 4:13 PM, Dave Abrahams via
 swift-evolution 
 > 
 wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson
 >
 wrote:
 
>>> 
>> , but haven't realized
>> that if you step around the type relationships encoded in Self
>> requirements and associated types you end up with types that 
>> appear to
>> interoperate but in fact trap at runtime unless used in exactly 
>> the
>> right way.
> 
> Trap at runtime?  How so?  Generalized existentials should still 
> be
> type-safe.  
 
 There are two choices when you erase static type relationships:
 
 1. Acheive type-safety by trapping at runtime
 
 FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
 
 2. Don't expose protocol requirements that involve these 
 relationships,
 which would prevent the code above from compiling and prevent
 FloatingPoint from conforming to itself.
 
> Or are you talking about the hypothetical types / behaviors people
> think they want when they don’t fully understand what is 
> happening...
 
 I don't know what you mean here.  I think generalized existentials 
 will
 be nice to have, but I think most people will want them to do 
 something
 they can't possibly do.
>>> 
>>> Exactly.  What I meant is that people think they want that 
>>> expression
>>> to compile because they don’t understand that the only thing it can 
>>> do
>>> is trap.  I said “hypothetical” because producing a compile time 
>>> error
>>> rather than a runtime trap is the only sane thing to do.  Your 
>>> comment
>>> surprised me because I can’t imagine we would move forward in Swift
>>> with the approach of trapping.
>> 
>> I would very much like to be able to create instances of “Collection
>> where Element == Int” so we can throw away the wrappers in the 
>> stdlib.
>> That will require some type mismatches to be caught at runtime via
>> trapping.
> 
> For invalid index because the existential accepts a type erased index?
 
 Exactly.
 
> How do you decide where to draw the line here?  It feels like a very
> slippery slope for a language where safety is a stated priority to
> start adopting a strategy of runtime trapping for something as
> fundamental as how you expose members on an existential.
 
 If you don't do this, the alternative is that “Collection where Element
 == Int” does not conform to Collection.  
>>> 
>>> This isn’t directly related to having self or associated type
>>> requirements.  It is true of all existentials.  
>> 
>> That is just an implementation limitation today, IIUC. 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-10 Thread Thorsten Seitz via swift-evolution

> Am 09.06.2016 um 19:50 schrieb Thorsten Seitz via swift-evolution 
> :
> 
> 
>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>> :
>> 
>> 
>> on Wed Jun 08 2016, Jordan Rose  wrote:
>> 
 On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
  wrote:
 
 
 on Wed Jun 08 2016, Thorsten Seitz
>>> 
 >
 wrote:
 
> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> to read up again what the reasons are for that behavior).
 
 Yes, but in the case of the issue we're discussing, the choices are:
 
 1. Omit from the existential's API any protocol requirements that depend
 on Self or associated types, in which case it *can't* conform to
 itself because it doesn't fulfill the requirements.
 
 2. Erase type relationships and trap at runtime when they don't line up.
 
 Matthew has been arguing against #2, but you can't “fix the bug” without
 it.
>>> 
>>> #1 has been my preference for a while as well, at least as a starting
>>> point. 
>> 
>> I should point out that with the resyntaxing of existentials to
>> Any, the idea that Collection's existential doesn't
>> conform to Collection becomes far less absurd than it was, so maybe this
>> is not so bad.
> 
> I think the problem is more that Any does not conform to a 
> specific value for a type parameter T: Collection
> 
> What I mean by this is that `Collection` denotes a type family, a generic 
> parameter `T: Collection` denotes a specific (though unknown) member of that 
> type family and `Any` denotes the type family again, so there is 
> really no point in writing Any IMO. 
> The type family cannot conform to T because T is just one fixed member of it.
> It conforms to itself, though, as I can write
> let c1: Any = …
> let c2: Any = c1
> 
> That’s why I think that we could just drop Any and simply write 
> Collection.


Let me expand that a bit:

Actually all this talk about existentials vs. generics or protocols vs. classes 
has had me confused somewhat and I think there are still some misconceptions 
present on this list sometimes, so I’ll try to clear them up:

(1) misconception: protocols with associated types are somehow very different 
from generics

I don’t think they are and I will explain why. The only difference is the way 
the type parameters are bound: generics use explicit parameter lists whereas 
protocols use inheritance. That has some advantages (think long parameter lists 
of generics) and some disadvantages.
These ways are dual in a notation sense: generic types have to have all 
parameters bound whereas protocols cannot bind any of them.
The „existential“ notation `Any<>` being discussed on this list is nothing more 
than adding the ability to protocols to bind the parameters to be used just 
like Java’s wildcards are adding the opposite feature to generics, namely not 
having to bind all parameters.

Essentially `Any` in Swift is just the same as `Collection` in 
Java (assuming for comparability’s sake that Swift’s Collection had no 
additional associated types; otherwise I would just have to introduce a 
Collection in Java).

Likewise `Any` is just the same as 
`Collection` in Java.

And just like Collection does not conform to a type parameter `T extends 
Collection` because Collection is the type `forall E. Collection` 
whereas `T extends Collection` is the type `T. Collection` for a given T.

In essence protocols with associated types are like generics with wildcards.

Coming back to the questions whether (a) allowing existentials to be used as 
types is useful and (b) whether sacrificing type safety would somehow be 
necessary for that, I think we can safely answer
(a) yes, it *is* useful to be able to use existentials like Any as 
types, because wildcards are quite often needed and very useful in Java (they 
haven’t been added without a reason)
(b) no, sacrificing type safety does not make sense, as the experience with 
Java’s wildcards shows that this is not needed. Especially if something like 
path dependent types is used like proposed and some notation to open an 
existential’s type is added, which is both something that Java does not have. 


(2) misconception: POP is different from OOP

It is not. Protocols are just interfaces using subtyping like OOP has always 
done. They just use associated types instead of explicit type parameters for 
generics (see above). The more important distinction of Swift is emphasizing 
value types and making mutation safely available by enforcing copy semantics 
for value types.
But protocols are not really different from interfaces in Java. I would have 
preferred a unified model using just classes with real multiple inheritance 
like Eiffel has and value types just being a part of that 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Matthew Johnson via swift-evolution

> On Jun 9, 2016, at 3:05 PM, Dave Abrahams  wrote:
> 
> 
> on Thu Jun 09 2016, Matthew Johnson  wrote:
> 
>>> On Jun 9, 2016, at 11:42 AM, Dave Abrahams  wrote:
>>> 
>>> 
>>> on Thu Jun 09 2016, Matthew Johnson >> > wrote:
>>> 
>> 
> On Jun 9, 2016, at 9:55 AM, Dave Abrahams  > wrote:
> 
> 
> on Wed Jun 08 2016, Matthew Johnson  
>  >> wrote:
> 
 
>>> On Jun 8, 2016, at 1:33 PM, Dave Abrahams >> > wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson >> > wrote:
>>> 
>> 
> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  > wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  
>  >> wrote:
> 
 
>>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via
>>> swift-evolution >> > wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson >> > wrote:
>>> 
>> 
> , but haven't realized
> that if you step around the type relationships encoded in Self
> requirements and associated types you end up with types that 
> appear to
> interoperate but in fact trap at runtime unless used in exactly 
> the
> right way.
 
 Trap at runtime?  How so?  Generalized existentials should still be
 type-safe.  
>>> 
>>> There are two choices when you erase static type relationships:
>>> 
>>> 1. Acheive type-safety by trapping at runtime
>>> 
>>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>>> 
>>> 2. Don't expose protocol requirements that involve these 
>>> relationships,
>>> which would prevent the code above from compiling and prevent
>>> FloatingPoint from conforming to itself.
>>> 
 Or are you talking about the hypothetical types / behaviors people
 think they want when they don’t fully understand what is 
 happening...
>>> 
>>> I don't know what you mean here.  I think generalized existentials 
>>> will
>>> be nice to have, but I think most people will want them to do 
>>> something
>>> they can't possibly do.
>> 
>> Exactly.  What I meant is that people think they want that expression
>> to compile because they don’t understand that the only thing it can 
>> do
>> is trap.  I said “hypothetical” because producing a compile time 
>> error
>> rather than a runtime trap is the only sane thing to do.  Your 
>> comment
>> surprised me because I can’t imagine we would move forward in Swift
>> with the approach of trapping.
> 
> I would very much like to be able to create instances of “Collection
> where Element == Int” so we can throw away the wrappers in the stdlib.
> That will require some type mismatches to be caught at runtime via
> trapping.
 
 For invalid index because the existential accepts a type erased index?
>>> 
>>> Exactly.
>>> 
 How do you decide where to draw the line here?  It feels like a very
 slippery slope for a language where safety is a stated priority to
 start adopting a strategy of runtime trapping for something as
 fundamental as how you expose members on an existential.
>>> 
>>> If you don't do this, the alternative is that “Collection where Element
>>> == Int” does not conform to Collection.  
>> 
>> This isn’t directly related to having self or associated type
>> requirements.  It is true of all existentials.  
> 
> That is just an implementation limitation today, IIUC.  What I'm talking
> about here would make it impossible for some to do that.
 
 If it is just an implementation limitation I am happy to hear that.
 
> 
>> If that changes for simple existentials and generalized existentials
>> expose all members (as in the latest draft of the proposal) maybe it
>> will be possible for all existentials to conform to their protocol.
> 
> Not without introducing runtime traps.  See my “subscript function”
> example.
 
> 
>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Dave Abrahams via swift-evolution

on Thu Jun 09 2016, Matthew Johnson  wrote:

>> On Jun 9, 2016, at 11:42 AM, Dave Abrahams  wrote:
>> 
>> 
>> on Thu Jun 09 2016, Matthew Johnson > > wrote:
>> 
>
 On Jun 9, 2016, at 9:55 AM, Dave Abrahams > wrote:
 
 
 on Wed Jun 08 2016, Matthew Johnson >>> 
 >> wrote:
 
>>> 
>> On Jun 8, 2016, at 1:33 PM, Dave Abrahams > > wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > > wrote:
>> 
> 
 On Jun 7, 2016, at 9:15 PM, Dave Abrahams > wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson >>> 
 >> wrote:
 
>>> 
>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via
>> swift-evolution > > wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > > wrote:
>> 
> 
 , but haven't realized
 that if you step around the type relationships encoded in Self
 requirements and associated types you end up with types that 
 appear to
 interoperate but in fact trap at runtime unless used in exactly the
 right way.
>>> 
>>> Trap at runtime?  How so?  Generalized existentials should still be
>>> type-safe.  
>> 
>> There are two choices when you erase static type relationships:
>> 
>> 1. Acheive type-safety by trapping at runtime
>> 
>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>> 
>> 2. Don't expose protocol requirements that involve these 
>> relationships,
>> which would prevent the code above from compiling and prevent
>> FloatingPoint from conforming to itself.
>> 
>>> Or are you talking about the hypothetical types / behaviors people
>>> think they want when they don’t fully understand what is 
>>> happening...
>> 
>> I don't know what you mean here.  I think generalized existentials 
>> will
>> be nice to have, but I think most people will want them to do 
>> something
>> they can't possibly do.
> 
> Exactly.  What I meant is that people think they want that expression
> to compile because they don’t understand that the only thing it can do
> is trap.  I said “hypothetical” because producing a compile time error
> rather than a runtime trap is the only sane thing to do.  Your comment
> surprised me because I can’t imagine we would move forward in Swift
> with the approach of trapping.
 
 I would very much like to be able to create instances of “Collection
 where Element == Int” so we can throw away the wrappers in the stdlib.
 That will require some type mismatches to be caught at runtime via
 trapping.
>>> 
>>> For invalid index because the existential accepts a type erased index?
>> 
>> Exactly.
>> 
>>> How do you decide where to draw the line here?  It feels like a very
>>> slippery slope for a language where safety is a stated priority to
>>> start adopting a strategy of runtime trapping for something as
>>> fundamental as how you expose members on an existential.
>> 
>> If you don't do this, the alternative is that “Collection where Element
>> == Int” does not conform to Collection.  
> 
> This isn’t directly related to having self or associated type
> requirements.  It is true of all existentials.  
 
 That is just an implementation limitation today, IIUC.  What I'm talking
 about here would make it impossible for some to do that.
>>> 
>>> If it is just an implementation limitation I am happy to hear that.
>>> 
 
> If that changes for simple existentials and generalized existentials
> expose all members (as in the latest draft of the proposal) maybe it
> will be possible for all existentials to conform to their protocol.
 
 Not without introducing runtime traps.  See my “subscript function”
 example.
>>> 
 
> 
>> That's weird and not very
>> useful.  You could expose all the methods that were on protocol
>> extensions of Collection on this existential, unless they used
>> associated types other than the element type.  But you couldn't pass the

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread L Mihalkovic via swift-evolution

> On Jun 9, 2016, at 7:29 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
>> Am 09.06.2016 um 00:18 schrieb Dave Abrahams via swift-evolution 
>> >:
>> 
>> Exactly.  But much simpler cases will also either have to trap at
>> runtime or be prohibited outright:
>> 
>>  func subscript_(c: C, i: C.Index) -> C.Collection.Element {
>>return c[i]
>>  }
> 
>>  typealias IntCollection = Any
>>  let c1: IntCollection = ...
>>  let c2: IntCollection = c1[3..<10]
>>  let c3: IntCollection = ...
>>  let c4: IntCollection = c1.reversed()
>> 
>>  // Note: the underlying index types are the same, and are supposed to
>>  // interoperate.  What do you do (work/trap/nocompile)?
>>  _ = subscript_(c1, c2.startIndex)
>> 
>>  // The underlying index types happen to be the same, and are not
>>  // supposed to interoperate.  What do you do (silently 
>> “work”/trap/nocompile)?
>>  _ = subscript_(c1, c3.startIndex)
>> 
>>  // The underlying index types are different.  What do you do 
>> (trap/nocompile)?
>>  _ = subscript_(c1, c4.startIndex)
> 
> 
> All of these are type errors. All we know about c1, c2, c3 and c4 is that 
> they are of type `Any` which does not 
> constrain the Index type, so all we know is that each variable can have a 
> different Index type. So, the type system can only say, no, these are type 
> errors.
> 
> On a second thought this example reads a little bit like the following:
> 
> let x1: Object = …
> let x2: Object = „hello"
> 
> // work/trap/nocompile?
> x1.characters
> 
> // x2 happens to be a String
> // work/trap/nocompile?
> x2.characters
> 
> I think we all agree that all these are type errors even though we know that 
> x2 contains a String and it might be useful to work in some cases. Maybe :-)
> 
> The same applies to the examples above IMO. The static knowledge is not 
> sufficient for those examples to compile.
> 
> 
> But thinking of path dependent types the following should work:

scala will soon have a ‘official' LLVM back-end… so that might soon be 
accessible to iOS devs

> 
> let c1: IntCollection = …
> let c2: c1.Type = c1[3..<10]
> 
> subscript_(c1, c2.startIndex) // ok!
> 
> 
> -Thorsten
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread L Mihalkovic via swift-evolution

> On Jun 9, 2016, at 7:50 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
>> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
>> :
>> 
>> 
>> on Wed Jun 08 2016, Jordan Rose  wrote:
>> 
 On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
  wrote:
 
 
 on Wed Jun 08 2016, Thorsten Seitz
>>> 
 >
 wrote:
 
> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> to read up again what the reasons are for that behavior).
 
 Yes, but in the case of the issue we're discussing, the choices are:
 
 1. Omit from the existential's API any protocol requirements that depend
 on Self or associated types, in which case it *can't* conform to
 itself because it doesn't fulfill the requirements.
 
 2. Erase type relationships and trap at runtime when they don't line up.
 
 Matthew has been arguing against #2, but you can't “fix the bug” without
 it.
>>> 
>>> #1 has been my preference for a while as well, at least as a starting
>>> point. 
>> 
>> I should point out that with the resyntaxing of existentials to
>> Any, the idea that Collection's existential doesn't
>> conform to Collection becomes far less absurd than it was, so maybe this
>> is not so bad.
> 
> I think the problem is more that Any does not conform to a 
> specific value for a type parameter T: Collection
> 
> What I mean by this is that `Collection` denotes a type family, a generic 
> parameter `T: Collection` denotes a specific (though unknown) member of that 
> type family and `Any` denotes the type family again, so there is 
> really no point in writing Any IMO. 
> The type family cannot conform to T because T is just one fixed member of it.
> It conforms to itself, though, as I can write
> let c1: Any = …
> let c2: Any = c1
> 
> That’s why I think that we could just drop Any and simply write 
> Collection.

I was exploring this path a bit… 

https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef



> -Thorsten
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread L Mihalkovic via swift-evolution

> On Jun 9, 2016, at 6:49 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Wed Jun 08 2016, Jordan Rose  wrote:
> 
>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>  wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Thorsten Seitz
>> 
>>> >> >
>>> wrote:
>>> 
 Ah, thanks, I forgot!  I still consider this a bug, though (will have
 to read up again what the reasons are for that behavior).
>>> 
>>> Yes, but in the case of the issue we're discussing, the choices are:
>>> 
>>> 1. Omit from the existential's API any protocol requirements that depend
>>>  on Self or associated types, in which case it *can't* conform to
>>>  itself because it doesn't fulfill the requirements.
>>> 
>>> 2. Erase type relationships and trap at runtime when they don't line up.
>>> 
>>> Matthew has been arguing against #2, but you can't “fix the bug” without
>>> it.
>> 
>> #1 has been my preference for a while as well, at least as a starting
>> point. 
> 
> I should point out that with the resyntaxing of existentials to
> Any, the idea that Collection's existential doesn't
> conform to Collection becomes far less absurd than it was, so maybe this
> is not so bad.

the issue I have will all proposed Any<…> so far is that they are rather heavy, 
and in the case of a replacement for the obj-c   id or 
worse MyTVC (I know the example is absurd for it stands 
for a specific concrete type conforming), it involves a bit of magic. So played 
with a little toy syntax starting from the sugaring you are doing for literals:

Array  —> [X]
Dict —> [X:Y]

stretching it to consider that existential are a degenerate form of literal 
notation, then the following would not look entirely out of place

https://gist.github.com/lmihalkovic/8aa66542f5cc4592e967bade260477ef

[last example unfinished - missing opening syntax]



> 
> -- 
> Dave
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread L Mihalkovic via swift-evolution

> On Jun 9, 2016, at 4:55 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Wed Jun 08 2016, Matthew Johnson  > wrote:
> 
>>> On Jun 8, 2016, at 1:33 PM, Dave Abrahams  wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson  wrote:
>>> 
>> 
> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  > wrote:
> 
 
>>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson  wrote:
>>> 
>> 
> , but haven't realized
> that if you step around the type relationships encoded in Self
> requirements and associated types you end up with types that appear to
> interoperate but in fact trap at runtime unless used in exactly the
> right way.
 
 Trap at runtime?  How so?  Generalized existentials should still be
 type-safe.  
>>> 
>>> There are two choices when you erase static type relationships:
>>> 
>>> 1. Acheive type-safety by trapping at runtime
>>> 
>>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>>> 
>>> 2. Don't expose protocol requirements that involve these relationships,
>>> which would prevent the code above from compiling and prevent
>>> FloatingPoint from conforming to itself.
>>> 
 Or are you talking about the hypothetical types / behaviors people
 think they want when they don’t fully understand what is happening...
>>> 
>>> I don't know what you mean here.  I think generalized existentials will
>>> be nice to have, but I think most people will want them to do something
>>> they can't possibly do.
>> 
>> Exactly.  What I meant is that people think they want that expression
>> to compile because they don’t understand that the only thing it can do
>> is trap.  I said “hypothetical” because producing a compile time error
>> rather than a runtime trap is the only sane thing to do.  Your comment
>> surprised me because I can’t imagine we would move forward in Swift
>> with the approach of trapping.
> 
> I would very much like to be able to create instances of “Collection
> where Element == Int” so we can throw away the wrappers in the stdlib.
> That will require some type mismatches to be caught at runtime via
> trapping.
 
 For invalid index because the existential accepts a type erased index?
>>> 
>>> Exactly.
>>> 
 How do you decide where to draw the line here?  It feels like a very
 slippery slope for a language where safety is a stated priority to
 start adopting a strategy of runtime trapping for something as
 fundamental as how you expose members on an existential.
>>> 
>>> If you don't do this, the alternative is that “Collection where Element
>>> == Int” does not conform to Collection.  
>> 
>> This isn’t directly related to having self or associated type
>> requirements.  It is true of all existentials.  
> 
> That is just an implementation limitation today, IIUC.  What I'm talking
> about here would make it impossible for some to do that.
> 
>> If that changes for simple existentials and generalized existentials
>> expose all members (as in the latest draft of the proposal) maybe it
>> will be possible for all existentials to conform to their protocol.
> 
> Not without introducing runtime traps.  See my “subscript function”
> example.
> 
>> 
>>> That's weird and not very
>>> useful.  You could expose all the methods that were on protocol
>>> extensions of Collection on this existential, unless they used
>>> associated types other than the element type.  But you couldn't pass the
>>> existential to a generic function like
>>> 
>>>  func scrambled(_ c: C) -> [C.Element]
>>> 
 IMO you should *have* to introduce unsafe behavior like that manually.
>>> 
>>> Collection where Element == Int & Index == *
>>> 
>>> ?
>> 
>> I didn’t mean directly through the type of the existential.
> 
> My question is, why not?  That is still explicit.
> 
>> One obvious mechanism for introducing unsafe behavior is to write
>> manual type erasure wrappers like we do today.
>> 
>> Another possibility would be to allow extending the existential type
>> (not the protocol).  This would allow you to write overloads on the
>> Collection existential that takes some kind of type erased index if
>> that is what you want and either trap if you receive an invalid index
>> or better (IMO) return an `Element?`.  I’m not sure how extensions on
>> existentials might be implemented, but this is an example of the kind
>> of operation you might want available on it that you wouldn’t want
>> available on all Collection types.
>> 
>>> 
 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Russ Bishop via swift-evolution

> On Jun 9, 2016, at 9:42 AM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> If your code has many manual type erasing wrappers corresponding to
> protocols with associated types and/or Self requirements that also never
> have to trap type mismatches, that would certainly be instructive
> empirical data.  Would you care to share the protocols and wrappers you
> are talking about?
> 
> 
> -- 
> Dave



Part of the problem is you get used to living inside the cell and forget what 
life might be like on the outside. I don’t run in to many cases anymore because 
I know they won’t work and pre-emotively constrain my designs to fit into the 
existing restrictions.

Sorry for the long bit of code, I tried to boil it down to the absolute 
minimum. It has the advantage of being actual shipping code:

public protocol AnyMutationOperation {
func __mutate(object: Any) -> Any
}

public protocol MutationOperation: AnyMutationOperation {
associatedtype ObjectType: MutatableSyncable
func _mutate(object: ObjectType) -> ObjectType
}

public protocol MutatableSyncable {
var _operations: [AnyMutationOperation] { get set }
mutating func mutate(mutation: T) -> Self
}

extension MutatableSyncable {
mutating func mutate(mutation: T) -> Self { 
self._operations.append(mutation)
return mutation._mutate(self)
}
mutating func _mutate(mutation: AnyMutationOperation) -> Self {
return mutation.__mutate(self) as! Self
}
}

extension MutationOperation {
func __mutate(object: Any) -> Any {
return self._mutate(object as! ObjectType)
}
}

struct Model: MutatableSyncable {
var _operations: [AnyMutationOperation] = []
var name: String = ""
}

struct ChangeNameOperation: MutationOperation {
var newName: String
func _mutate(object: Model) -> Model {
var copy = object
copy.name = self.newName
return object
}
}


AnyMutationOperation, the force casting, etc are all to work around the 
inability to call MutatableSyncable.mutate() with MutationOperations that came 
from the database. 

// at local point of mutation, works fine
var model = Model()
let op = ChangeNameOperation(newName: "bob")
model.mutate(op)


// when trying to rollback/rollforward in sync manager, which handles many 
model and mutation types
var model: MutatableSyncable = …
// this can't even be MutationOperation
let op: AnyMutationOperation = …

// ERROR, can't do that!
//model.mutate(op)

// Better hope none of those force casts trap!
model._mutate(op)

We didn’t want to encode a massive list of 100s of types in a big ol’ switch 
statement because we’re modeling every single mutable field as a separate 
MutationOperation. All we know in the sync manager is we have a 
MutatableSyncable and some MutationOperation (but in our type-erased 
AnyMutationOperation). So we have a fragile system that traps if anyone makes a 
mistake. I’d much rather be able to unwrap the existential and validate that 
the operation’s ObjectType matches the model’s concrete type, then call the 
generic version of mutate().

There is another place where we want to find the ObjectManager 
for the model type T, then call it but we run into the same associated types 
problem. We couldn’t create a Dictionary 
because ObjectManager has associated types.

In that case the list of model types was constrained enough we went for the big 
switch statement but it takes Any so is completely unchecked by the compiler 
even though we know that we could constrain it to be type safe:

func saveFromServer(model: Any) throws {
switch model {
case let model as PGReportTypeFullModel:
try self.reportTypeManager.saveFromServer(model)
// lots of others here ...
}
}


I’ll see if I can find some more examples later.

Russ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Thorsten Seitz via swift-evolution

> Am 09.06.2016 um 19:24 schrieb Austin Zheng via swift-evolution 
> :
> 
> On Thu, Jun 9, 2016 at 9:42 AM, Dave Abrahams via swift-evolution 
> > wrote:
> 
> on Thu Jun 09 2016, Matthew Johnson  wrote: 
> >
> >>
> >>> Introducing a language (not library) mechanism that exposes members on
> >>> generalized existentials in a way that relies on runtime traps for
> >>> type safety feels to me like a pretty dramatic turn agains the stated
> >>> priority of safety.  It will mean you must understand exactly what is
> >>> going on and be extremely careful to use generalized existentials
> >>> without causing crashes.  This will either make Swift code much more
> >>> crashy or will scare people away from using generalized existentials
> >>> (and maybe both).
> >>
> >> I don't accept either of those statements without seeing some analysis
> >> of the use-cases.  For example, I don't believe that AnyCollection et al
> >> are particularly crash-prone.  The likelihood that you'll use the wrong
> >> index type with a collection is very, very low.  I'm less certain of
> >> what happens with Self requirements in real cases.
> >
> > But again, I believe this is an exceptional case as the precondition
> > is explicitly stated in the semantics of the protocol.
> 
> IIUC, it has been cited by Doug as the exemplar of the
> predominantly-requested case by a 10:1 ratio!
> 
> At the risk of sounding waffly, I see both sides of the argument.
> 
> Java is typesafe in the formal sense (can't perform an operation on a type 
> that doesn't actually support it); almost certainly moreso than Swift (which 
> lets you do wonderful things like reinterpret casting, C-style direct memory 
> manipulation...).
> 
> However, in many cases Swift provides better compile-time assurances than 
> Java. In Java, any reference might actually be a null reference waiting to 
> cause a NullPointerException unless you explicitly check it in code (and what 
> if you forget to check it somewhere?). In Swift, (aside from IUOs and a few 
> other features) if your program compiles successfully the type checker has 
> proven that your software will never try calling a method upon nil. And if 
> you do use IUOs the postfix exclamation marks clearly mark spots in your code 
> that might cause trouble.
> 
> In the same way I don't think trapping at runtime if an existential 
> satisfying a generic type parameter causes a type error is the best solution 
> to this problem. What we are doing is allowing a type that makes a weak 
> guarantee to stand in for a type that makes a strong guarantee, and catching 
> mismatches between those guarantees if/when they pop up. There's no easy way 
> for someone perusing the code to tell that such a mismatch might occur, 
> equivalent to IUO's postfix !.
> 
> What I prefer is to explicitly "promote" the type with the weak guarantee to 
> a type with the stronger guarantee using the existential opening mechanism 
> that we've been throwing around. That way, it's very clear what is going on: 
> if the existentials in question can't serve as generic parameters to the 
> function you want to pass them to, you can fatalError() or do something else. 
> Or you can try force-opening with `as!` and mark a potential trouble spot in 
> the same way an IUO does. Once it succeeds you know you have the strong 
> guarantees that will cause your generic member to alway work the way it 
> should.

Yes, there should never be crashes for calling a wrong method. That is what 
*type* safety means.
You still can have crashes when calling a method with wrong arguments. To make 
that type safe you would need a type system with dependent typing.

I think that Swift should not only always be safe but that it should always be 
type safe, too.

-Thorsten


> 
> With the proposed mechanism, I expect that Any T> should be less prone to runtime trapping than AnyCollection, because we 
> can reify the concept that each instance of the existential has a concrete 
> Index type associated with it, rather than relying upon a type-erased 
> AnyIndex shared among all AnyCollections. (That being said, I don't know if 
> AnyCollection is particularly problematic in practical use. I also don't know 
> if other type-erased wrappers users might define might be more or less prone 
> to this type of issue.)
> 
> 
> > IMO the burden of proof should be on the side that proposes a
> > mechanism to introduce traps, not the side that proposes avoiding
> > them.
> 
> If you really want to make this about sides and burdens, the burden of
> proof always rests with the side proposing to extend the language.  We
> shouldn't be making changes without understanding how they will play out
> in real use-cases.
> 
> 
> Yes, I really want to see real-world use cases.
>  
> >>
> >> Neither of these look like they actually make *use* of the fact that
> >> there's type erasure involved (and therefore 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Thorsten Seitz via swift-evolution

> Am 09.06.2016 um 18:49 schrieb Dave Abrahams via swift-evolution 
> :
> 
> 
> on Wed Jun 08 2016, Jordan Rose  wrote:
> 
>>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>>  wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Thorsten Seitz
>> 
>>> >> >
>>> wrote:
>>> 
 Ah, thanks, I forgot!  I still consider this a bug, though (will have
 to read up again what the reasons are for that behavior).
>>> 
>>> Yes, but in the case of the issue we're discussing, the choices are:
>>> 
>>> 1. Omit from the existential's API any protocol requirements that depend
>>>  on Self or associated types, in which case it *can't* conform to
>>>  itself because it doesn't fulfill the requirements.
>>> 
>>> 2. Erase type relationships and trap at runtime when they don't line up.
>>> 
>>> Matthew has been arguing against #2, but you can't “fix the bug” without
>>> it.
>> 
>> #1 has been my preference for a while as well, at least as a starting
>> point. 
> 
> I should point out that with the resyntaxing of existentials to
> Any, the idea that Collection's existential doesn't
> conform to Collection becomes far less absurd than it was, so maybe this
> is not so bad.

I think the problem is more that Any does not conform to a specific 
value for a type parameter T: Collection

What I mean by this is that `Collection` denotes a type family, a generic 
parameter `T: Collection` denotes a specific (though unknown) member of that 
type family and `Any` denotes the type family again, so there is 
really no point in writing Any IMO. 
The type family cannot conform to T because T is just one fixed member of it.
It conforms to itself, though, as I can write
let c1: Any = …
let c2: Any = c1

That’s why I think that we could just drop Any and simply write 
Collection.

-Thorsten
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Thorsten Seitz via swift-evolution

> Am 09.06.2016 um 00:18 schrieb Dave Abrahams via swift-evolution 
> :
> 
> Exactly.  But much simpler cases will also either have to trap at
> runtime or be prohibited outright:
> 
>  func subscript_(c: C, i: C.Index) -> C.Collection.Element {
>return c[i]
>  }

>  typealias IntCollection = Any
>  let c1: IntCollection = ...
>  let c2: IntCollection = c1[3..<10]
>  let c3: IntCollection = ...
>  let c4: IntCollection = c1.reversed()
> 
>  // Note: the underlying index types are the same, and are supposed to
>  // interoperate.  What do you do (work/trap/nocompile)?
>  _ = subscript_(c1, c2.startIndex)
> 
>  // The underlying index types happen to be the same, and are not
>  // supposed to interoperate.  What do you do (silently 
> “work”/trap/nocompile)?
>  _ = subscript_(c1, c3.startIndex)
> 
>  // The underlying index types are different.  What do you do 
> (trap/nocompile)?
>  _ = subscript_(c1, c4.startIndex)


All of these are type errors. All we know about c1, c2, c3 and c4 is that they 
are of type `Any` which does not constrain the 
Index type, so all we know is that each variable can have a different Index 
type. So, the type system can only say, no, these are type errors.

On a second thought this example reads a little bit like the following:

let x1: Object = …
let x2: Object = „hello"

// work/trap/nocompile?
x1.characters

// x2 happens to be a String
// work/trap/nocompile?
x2.characters

I think we all agree that all these are type errors even though we know that x2 
contains a String and it might be useful to work in some cases. Maybe :-)

The same applies to the examples above IMO. The static knowledge is not 
sufficient for those examples to compile.


But thinking of path dependent types the following should work:

let c1: IntCollection = …
let c2: c1.Type = c1[3..<10]

subscript_(c1, c2.startIndex) // ok!


-Thorsten


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Matthew Johnson via swift-evolution

> On Jun 9, 2016, at 11:42 AM, Dave Abrahams  wrote:
> 
> 
> on Thu Jun 09 2016, Matthew Johnson  > wrote:
> 
>>> On Jun 9, 2016, at 9:55 AM, Dave Abrahams >> > wrote:
>>> 
>>> 
>>> on Wed Jun 08 2016, Matthew Johnson >>  >> >> wrote:
>>> 
>> 
> On Jun 8, 2016, at 1:33 PM, Dave Abrahams  > wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  > wrote:
> 
 
>>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams >> > wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson >>  >> >> wrote:
>>> 
>> 
> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
> > wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  > wrote:
> 
 
>>> , but haven't realized
>>> that if you step around the type relationships encoded in Self
>>> requirements and associated types you end up with types that appear 
>>> to
>>> interoperate but in fact trap at runtime unless used in exactly the
>>> right way.
>> 
>> Trap at runtime?  How so?  Generalized existentials should still be
>> type-safe.  
> 
> There are two choices when you erase static type relationships:
> 
> 1. Acheive type-safety by trapping at runtime
> 
> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
> 
> 2. Don't expose protocol requirements that involve these 
> relationships,
> which would prevent the code above from compiling and prevent
> FloatingPoint from conforming to itself.
> 
>> Or are you talking about the hypothetical types / behaviors people
>> think they want when they don’t fully understand what is happening...
> 
> I don't know what you mean here.  I think generalized existentials 
> will
> be nice to have, but I think most people will want them to do 
> something
> they can't possibly do.
 
 Exactly.  What I meant is that people think they want that expression
 to compile because they don’t understand that the only thing it can do
 is trap.  I said “hypothetical” because producing a compile time error
 rather than a runtime trap is the only sane thing to do.  Your comment
 surprised me because I can’t imagine we would move forward in Swift
 with the approach of trapping.
>>> 
>>> I would very much like to be able to create instances of “Collection
>>> where Element == Int” so we can throw away the wrappers in the stdlib.
>>> That will require some type mismatches to be caught at runtime via
>>> trapping.
>> 
>> For invalid index because the existential accepts a type erased index?
> 
> Exactly.
> 
>> How do you decide where to draw the line here?  It feels like a very
>> slippery slope for a language where safety is a stated priority to
>> start adopting a strategy of runtime trapping for something as
>> fundamental as how you expose members on an existential.
> 
> If you don't do this, the alternative is that “Collection where Element
> == Int” does not conform to Collection.  
 
 This isn’t directly related to having self or associated type
 requirements.  It is true of all existentials.  
>>> 
>>> That is just an implementation limitation today, IIUC.  What I'm talking
>>> about here would make it impossible for some to do that.
>> 
>> If it is just an implementation limitation I am happy to hear that.
>> 
>>> 
 If that changes for simple existentials and generalized existentials
 expose all members (as in the latest draft of the proposal) maybe it
 will be possible for all existentials to conform to their protocol.
>>> 
>>> Not without introducing runtime traps.  See my “subscript function”
>>> example.
>> 
>>> 
 
> That's weird and not very
> useful.  You could expose all the methods that were on protocol
> extensions of Collection on this existential, unless they used
> associated types other than the element type.  But you couldn't pass the
> existential to a generic function like
> 
> func scrambled(_ c: C) -> [C.Element]
> 
>> IMO you should *have* to introduce unsafe behavior like that manually.
> 
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Austin Zheng via swift-evolution
On Thu, Jun 9, 2016 at 9:42 AM, Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Thu Jun 09 2016, Matthew Johnson  wrote:

>
> >>
> >>> Introducing a language (not library) mechanism that exposes members on
> >>> generalized existentials in a way that relies on runtime traps for
> >>> type safety feels to me like a pretty dramatic turn agains the stated
> >>> priority of safety.  It will mean you must understand exactly what is
> >>> going on and be extremely careful to use generalized existentials
> >>> without causing crashes.  This will either make Swift code much more
> >>> crashy or will scare people away from using generalized existentials
> >>> (and maybe both).
> >>
> >> I don't accept either of those statements without seeing some analysis
> >> of the use-cases.  For example, I don't believe that AnyCollection et al
> >> are particularly crash-prone.  The likelihood that you'll use the wrong
> >> index type with a collection is very, very low.  I'm less certain of
> >> what happens with Self requirements in real cases.
> >
> > But again, I believe this is an exceptional case as the precondition
> > is explicitly stated in the semantics of the protocol.
>
> IIUC, it has been cited by Doug as the exemplar of the
> predominantly-requested case by a 10:1 ratio!
>

At the risk of sounding waffly, I see both sides of the argument.

Java is typesafe in the formal sense (can't perform an operation on a type
that doesn't actually support it); almost certainly moreso than Swift
(which lets you do wonderful things like reinterpret casting, C-style
direct memory manipulation...).

However, in many cases Swift provides better compile-time assurances than
Java. In Java, any reference might actually be a null reference waiting to
cause a NullPointerException unless you explicitly check it in code (and
what if you forget to check it somewhere?). In Swift, (aside from IUOs and
a few other features) if your program compiles successfully the type
checker has proven that your software will never try calling a method upon
nil. And if you do use IUOs the postfix exclamation marks clearly mark
spots in your code that might cause trouble.

In the same way I don't think trapping at runtime if an existential
satisfying a generic type parameter causes a type error is the best
solution to this problem. What we are doing is allowing a type that makes a
weak guarantee to stand in for a type that makes a strong guarantee, and
catching mismatches between those guarantees if/when they pop up. There's
no easy way for someone perusing the code to tell that such a mismatch
might occur, equivalent to IUO's postfix !.

What I prefer is to explicitly "promote" the type with the weak guarantee
to a type with the stronger guarantee using the existential opening
mechanism that we've been throwing around. That way, it's very clear what
is going on: if the existentials in question can't serve as generic
parameters to the function you want to pass them to, you can fatalError()
or do something else. Or you can try force-opening with `as!` and mark a
potential trouble spot in the same way an IUO does. Once it succeeds you
know you have the strong guarantees that will cause your generic member to
alway work the way it should.

With the proposed mechanism, I expect that Any should be less prone to runtime trapping than AnyCollection, because
we can reify the concept that each instance of the existential has a
concrete Index type associated with it, rather than relying upon a
type-erased AnyIndex shared among all AnyCollections. (That being said, I
don't know if AnyCollection is particularly problematic in practical use. I
also don't know if other type-erased wrappers users might define might be
more or less prone to this type of issue.)


> > IMO the burden of proof should be on the side that proposes a
> > mechanism to introduce traps, not the side that proposes avoiding
> > them.
>
> If you really want to make this about sides and burdens, the burden of
> proof always rests with the side proposing to extend the language.  We
> shouldn't be making changes without understanding how they will play out
> in real use-cases.
>
>
Yes, I really want to see real-world use cases.


> >>
> >> Neither of these look like they actually make *use* of the fact that
> >> there's type erasure involved (and therefore should probably be written
> >> as generics?).  The interesting cases with Any, for the
> >> purposes of this discussion, arise when you have multiple instances of
> >> the same existential type that wrap different concrete types.
> >
> > One use case I have found is to work around the lack of higher-kinder
> > types.
>
> Really, now: a use-case for feature A that is a workaround for the lack
> of feature B hardly justifies adding feature A!  We do want to add
> higher-kinded types eventually.
>

I just want to say, this made my day.

Most of the examples in the document Matthew linked were meant to be
didactic, not 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Thorsten Seitz via swift-evolution

> Am 09.06.2016 um 00:13 schrieb Matthew Johnson via swift-evolution 
> :
> 
> 
>> On Jun 8, 2016, at 4:47 PM, Austin Zheng > > wrote:
>> 
>> FWIW my opinion is that existentials either shouldn't be allowed to stand in 
>> for generic type parameters, or Dave's option #1 if they are.
>> 
>> The implied promise of a generic type parameter T right now is that T always 
>> stands for the same concrete type (modulo things like passing in a subclass 
>> where a class would do), and likewise for all of T's associated types (T.Foo 
>> is always the same type everywhere in the context where T is valid). This is 
>> what makes using anything with 'self' requirements in a generic context 
>> sound. Allowing existentials to satisfy T would violate that constraint. 
>> 
>> Relaxing these semantics would make it too easy to write code that traps at 
>> runtime "without the user having to reach" (to paraphrase Jordan from the 
>> "Swift philosophy" thread). Anyone who really really wants to write code 
>> that is 'compile-time unsound' in this way should have to explicitly type 
>> erase using concrete wrappers.
> 
> Yes, exactly.

Yup.

-Thorsten


> 
>> 
>> Best,
>> Austin
>> 
>> 
>> On Wed, Jun 8, 2016 at 2:37 PM, Austin Zheng > > wrote:
>> We might be talking past each other. I think Matthew is talking about using 
>> an existential outside the context of generic functions. For example, 
>> something like this should be trap-proof (as long as 'x' is immutable, which 
>> it is in this example):
>> 
>> func copySequenceIntoArray(x: Any) 
>> -> [Int] {
>>  var buffer : [Int] = []
>> // Stupid implementation to make a point
>>  var iterator : x.Iterator = x.makeIterator()
>>  while true {
>>  let nextItem : Int? = iterator.next()
>>  if let nextItem = nextItem {
>>  buffer.append(nextItem)
>>  } else {
>>  return buffer
>>  }
>>  }
>> }
>> 
>> Even this would never trap as well:
>> 
>> func copySequenceIntoArray(x: Any) 
>> -> [T] {
>>  var buffer : [T] = []
>>  for item in x {
>>  buffer.append(item)
>>  }
>>  return buffer
>> }
>> 
>> Where we run into difficulty is something like this (forgive my abuse of the 
>> collections API; I don't remember all the new indexing APIs off the top of 
>> my head):
>> 
>> func doSomething(x: T, y: T) {
>>  // Get indexes out of x and use them to index into y
>>  var idx = x.startIndex
>>  while (idx != x.endIndex || idx != y.endIndex) {
>>  print(x[idx])
>>  print(y[idx])
>>  idx = x.nextIndex(idx)
>>  }
>> }
>> let someSeq : Any = // ...
>> let anotherSeq : Any = // ...
>> // Trouble!
>> // someSeq and anotherSeq are the same existential type
>> // But the concrete index types within each of the existential variables may 
>> be different
>> doSomething(someSeq, anotherSeq)
>> 
>> It's this situation (using an existential type to fulfill a generic type 
>> parameter constrained to the same requirements that comprise that 
>> existential) that requires either of the two options that Dave presented, 
>> due to our lack of compile-time type information about the fulfilling type's 
>> associated types.
>> 
>> Best,
>> Austin
>> 
>> On Wed, Jun 8, 2016 at 2:33 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> > On Jun 8, 2016, at 3:16 PM, Dave Abrahams via swift-evolution 
>> > > wrote:
>> >
>> >
>> >> on Wed Jun 08 2016, Thorsten Seitz > >> > wrote:
>> >>
>> >> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> >> to read up again what the reasons are for that behavior).
>> >
>> > Yes, but in the case of the issue we're discussing, the choices are:
>> >
>> > 1. Omit from the existential's API any protocol requirements that depend
>> >   on Self or associated types, in which case it *can't* conform to
>> >   itself because it doesn't fulfill the requirements.
>> 
>> They don't need to be omitted.  They are exposed in different ways depending 
>> on how the existential is constrained.  Austin's proposal was originally 
>> written to omit some members but it was modified based on feedback from Doug 
>> Gregor IIRC (Austin, is that right?).  Now it contains examples showing how 
>> these members are made available in a safe way.   Some members may still not 
>> be usable because you can't form an argument but IIRC the suggestion was 
>> that they be exposed anyway for consistency.
>> 
>> >
>> > 2. Erase type relationships and trap at runtime when they don't line up.
>> >
>> > Matthew has been arguing against #2, but you 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Dave Abrahams via swift-evolution

on Wed Jun 08 2016, Jordan Rose  wrote:

>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz
>
>> > >
>> wrote:
>> 
>>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices are:
>> 
>> 1. Omit from the existential's API any protocol requirements that depend
>>   on Self or associated types, in which case it *can't* conform to
>>   itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't line up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” without
>> it.
>
> #1 has been my preference for a while as well, at least as a starting
> point. 

I should point out that with the resyntaxing of existentials to
Any, the idea that Collection's existential doesn't
conform to Collection becomes far less absurd than it was, so maybe this
is not so bad.

-- 
Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Dave Abrahams via swift-evolution

on Thu Jun 09 2016, Matthew Johnson  wrote:

>> On Jun 9, 2016, at 9:55 AM, Dave Abrahams  wrote:
>> 
>> 
>> on Wed Jun 08 2016, Matthew Johnson > > wrote:
>> 
>
 On Jun 8, 2016, at 1:33 PM, Dave Abrahams  wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson  wrote:
 
>>> 
>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > > wrote:
>> 
> 
 On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
  wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson  wrote:
 
>>> 
>> , but haven't realized
>> that if you step around the type relationships encoded in Self
>> requirements and associated types you end up with types that appear 
>> to
>> interoperate but in fact trap at runtime unless used in exactly the
>> right way.
> 
> Trap at runtime?  How so?  Generalized existentials should still be
> type-safe.  
 
 There are two choices when you erase static type relationships:
 
 1. Acheive type-safety by trapping at runtime
 
 FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
 
 2. Don't expose protocol requirements that involve these relationships,
 which would prevent the code above from compiling and prevent
 FloatingPoint from conforming to itself.
 
> Or are you talking about the hypothetical types / behaviors people
> think they want when they don’t fully understand what is happening...
 
 I don't know what you mean here.  I think generalized existentials will
 be nice to have, but I think most people will want them to do something
 they can't possibly do.
>>> 
>>> Exactly.  What I meant is that people think they want that expression
>>> to compile because they don’t understand that the only thing it can do
>>> is trap.  I said “hypothetical” because producing a compile time error
>>> rather than a runtime trap is the only sane thing to do.  Your comment
>>> surprised me because I can’t imagine we would move forward in Swift
>>> with the approach of trapping.
>> 
>> I would very much like to be able to create instances of “Collection
>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> That will require some type mismatches to be caught at runtime via
>> trapping.
> 
> For invalid index because the existential accepts a type erased index?
 
 Exactly.
 
> How do you decide where to draw the line here?  It feels like a very
> slippery slope for a language where safety is a stated priority to
> start adopting a strategy of runtime trapping for something as
> fundamental as how you expose members on an existential.
 
 If you don't do this, the alternative is that “Collection where Element
 == Int” does not conform to Collection.  
>>> 
>>> This isn’t directly related to having self or associated type
>>> requirements.  It is true of all existentials.  
>> 
>> That is just an implementation limitation today, IIUC.  What I'm talking
>> about here would make it impossible for some to do that.
>
> If it is just an implementation limitation I am happy to hear that.
>
>> 
>>> If that changes for simple existentials and generalized existentials
>>> expose all members (as in the latest draft of the proposal) maybe it
>>> will be possible for all existentials to conform to their protocol.
>> 
>> Not without introducing runtime traps.  See my “subscript function”
>> example.
>
>> 
>>> 
 That's weird and not very
 useful.  You could expose all the methods that were on protocol
 extensions of Collection on this existential, unless they used
 associated types other than the element type.  But you couldn't pass the
 existential to a generic function like
 
  func scrambled(_ c: C) -> [C.Element]
 
> IMO you should *have* to introduce unsafe behavior like that manually.
 
 Collection where Element == Int & Index == *
 
 ?
>>> 
>>> I didn’t mean directly through the type of the existential.
>> 
>> My question is, why not?  That is still explicit.
>
> It’s not explicit in the sense that nobody wrote `fatalError` or
> similar in their code.  It’s too easy to write something like that
> without realizing that it introduces the possibility of a crash.  If
> we adopt syntax like that to introduce an existential that introduces
> traps we should at least require members that can be trap to be
> invoked using a `!` suffix or something like that to make it clear to
> users that a trap will happen if they are not 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Thorsten Seitz via swift-evolution

> Am 08.06.2016 um 23:37 schrieb Austin Zheng via swift-evolution 
> :
> 
> func doSomething(x: T, y: T) {
>   // Get indexes out of x and use them to index into y
>   var idx = x.startIndex
>   while (idx != x.endIndex || idx != y.endIndex) {
>   print(x[idx])
>   print(y[idx])
>   idx = x.nextIndex(idx)
>   }
> }
> let someSeq : Any = // ...
> let anotherSeq : Any = // ...
> // Trouble!
> // someSeq and anotherSeq are the same existential type
> // But the concrete index types within each of the existential variables may 
> be different
> doSomething(someSeq, anotherSeq)
> 
> It's this situation (using an existential type to fulfill a generic type 
> parameter constrained to the same requirements that comprise that 
> existential) that requires either of the two options that Dave presented, due 
> to our lack of compile-time type information about the fulfilling type's 
> associated types.
> 

Ok, that’s indeed a type error and I think that I now see why Any does not conform to T: Collection where T.Element == 
Int. This is because T stands for one *fixed* type out of the set of types 
described by Any whereas Any stands for *all* of them, which is more, so it cannot conform 
to T.

So doSomething(someSeq, anotherSeq) would be a type error and I’m fine with 
that.

We could try to write

func doSomething>(x: T, y: T) { … }

but then we wouldn’t be able to write the body as desired, because x.Index 
would be a different type from y.Index (and rightly so).

I think all this is fine, though. The above method doSomething() can only be 
written with runtime casts of the indices by opening them explicitly with one 
of the proposed syntaxes.

-Thorsten



___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Austin Zheng via swift-evolution
Yes, you were correct. Thanks for spotting that and apologies for not
acknowledging you sooner.

Austin

On Thu, Jun 9, 2016 at 1:13 AM, L. Mihalkovic 
wrote:

>
> On Jun 9, 2016, at 8:06 AM, Austin Zheng  wrote:
>
> According to that code (which is in Decl.cpp), AnyObject (and Any)
> conforms to itself; no non-@objc protocol is allowed to conform to
> itself. An @objc protocol may or may not conform to itself, depending on
> some other conditions.
>
>
> Like I said... more sub-cases than your original statement, right?!
>
>
> On Jun 8, 2016, at 9:19 PM, L. Mihalkovic 
> wrote:
>
>
>
> On Jun 8, 2016, at 9:43 PM, Austin Zheng via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> It's not possible, even with Swift's current implementation of
> existentials. A protocol type P isn't considered to conform to itself, thus
> the following is rejected:
>
>
> The rules are not that simple, I seem to recall reading in sourcecode that
> there are criteria that decide if that is true or not. And by default the
> variable conform_to_self is even TRUE
>
>
>
> let a : MyProtocol = // ...
> func myFunc(x: T) {
>   // 
> }
> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type
> MyProtocol"
>
> Changing how this works is probably worth a proposal by itself.
>
> Austin
>
>
> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> > Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org>:
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson > > wrote:
>> >
>> >>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams 
>> wrote:
>> >>>
>> >>>
>> >>> on Tue Jun 07 2016, Matthew Johnson >  >
>> wrote:
>> >>>
>> >>
>> > On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson 
>> wrote:
>> >
>> 
>> >>> , but haven't realized
>> >>> that if you step around the type relationships encoded in Self
>> >>> requirements and associated types you end up with types that
>> appear to
>> >>> interoperate but in fact trap at runtime unless used in exactly
>> the
>> >>> right way.
>> >>
>> >> Trap at runtime?  How so?  Generalized existentials should still be
>> >> type-safe.
>> >
>> > There are two choices when you erase static type relationships:
>> >
>> > 1. Acheive type-safety by trapping at runtime
>> >
>> > FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>> >
>> > 2. Don't expose protocol requirements that involve these
>> relationships,
>> > which would prevent the code above from compiling and prevent
>> > FloatingPoint from conforming to itself.
>> >
>> >> Or are you talking about the hypothetical types / behaviors people
>> >> think they want when they don’t fully understand what is
>> happening...
>> >
>> > I don't know what you mean here.  I think generalized existentials
>> will
>> > be nice to have, but I think most people will want them to do
>> something
>> > they can't possibly do.
>> 
>>  Exactly.  What I meant is that people think they want that expression
>>  to compile because they don’t understand that the only thing it can
>> do
>>  is trap.  I said “hypothetical” because producing a compile time
>> error
>>  rather than a runtime trap is the only sane thing to do.  Your
>> comment
>>  surprised me because I can’t imagine we would move forward in Swift
>>  with the approach of trapping.
>> >>>
>> >>> I would very much like to be able to create instances of “Collection
>> >>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> >>> That will require some type mismatches to be caught at runtime via
>> >>> trapping.
>> >>
>> >> For invalid index because the existential accepts a type erased index?
>> >
>> > Exactly.
>> >
>> >> How do you decide where to draw the line here?  It feels like a very
>> >> slippery slope for a language where safety is a stated priority to
>> >> start adopting a strategy of runtime trapping for something as
>> >> fundamental as how you expose members on an existential.
>> >
>> > If you don't do this, the alternative is that “Collection where Element
>> > == Int” does not conform to Collection.  That's weird and not very
>> > useful.  You could expose all the methods that were on protocol
>> > extensions of Collection on this existential, unless they used
>> > associated types other than the element type.  But you couldn't pass the
>> > existential to a generic function like
>> >
>> >   func scrambled(_ c: C) -> [C.Element]
>>
>> I don’t understand. Why couldn’t an 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Matthew Johnson via swift-evolution

> On Jun 9, 2016, at 9:55 AM, Dave Abrahams  wrote:
> 
> 
> on Wed Jun 08 2016, Matthew Johnson  > wrote:
> 
>>> On Jun 8, 2016, at 1:33 PM, Dave Abrahams  wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson  wrote:
>>> 
>> 
> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  > wrote:
> 
 
>>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson  wrote:
>>> 
>> 
> , but haven't realized
> that if you step around the type relationships encoded in Self
> requirements and associated types you end up with types that appear to
> interoperate but in fact trap at runtime unless used in exactly the
> right way.
 
 Trap at runtime?  How so?  Generalized existentials should still be
 type-safe.  
>>> 
>>> There are two choices when you erase static type relationships:
>>> 
>>> 1. Acheive type-safety by trapping at runtime
>>> 
>>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>>> 
>>> 2. Don't expose protocol requirements that involve these relationships,
>>> which would prevent the code above from compiling and prevent
>>> FloatingPoint from conforming to itself.
>>> 
 Or are you talking about the hypothetical types / behaviors people
 think they want when they don’t fully understand what is happening...
>>> 
>>> I don't know what you mean here.  I think generalized existentials will
>>> be nice to have, but I think most people will want them to do something
>>> they can't possibly do.
>> 
>> Exactly.  What I meant is that people think they want that expression
>> to compile because they don’t understand that the only thing it can do
>> is trap.  I said “hypothetical” because producing a compile time error
>> rather than a runtime trap is the only sane thing to do.  Your comment
>> surprised me because I can’t imagine we would move forward in Swift
>> with the approach of trapping.
> 
> I would very much like to be able to create instances of “Collection
> where Element == Int” so we can throw away the wrappers in the stdlib.
> That will require some type mismatches to be caught at runtime via
> trapping.
 
 For invalid index because the existential accepts a type erased index?
>>> 
>>> Exactly.
>>> 
 How do you decide where to draw the line here?  It feels like a very
 slippery slope for a language where safety is a stated priority to
 start adopting a strategy of runtime trapping for something as
 fundamental as how you expose members on an existential.
>>> 
>>> If you don't do this, the alternative is that “Collection where Element
>>> == Int” does not conform to Collection.  
>> 
>> This isn’t directly related to having self or associated type
>> requirements.  It is true of all existentials.  
> 
> That is just an implementation limitation today, IIUC.  What I'm talking
> about here would make it impossible for some to do that.

If it is just an implementation limitation I am happy to hear that.

> 
>> If that changes for simple existentials and generalized existentials
>> expose all members (as in the latest draft of the proposal) maybe it
>> will be possible for all existentials to conform to their protocol.
> 
> Not without introducing runtime traps.  See my “subscript function”
> example.



> 
>> 
>>> That's weird and not very
>>> useful.  You could expose all the methods that were on protocol
>>> extensions of Collection on this existential, unless they used
>>> associated types other than the element type.  But you couldn't pass the
>>> existential to a generic function like
>>> 
>>>  func scrambled(_ c: C) -> [C.Element]
>>> 
 IMO you should *have* to introduce unsafe behavior like that manually.
>>> 
>>> Collection where Element == Int & Index == *
>>> 
>>> ?
>> 
>> I didn’t mean directly through the type of the existential.
> 
> My question is, why not?  That is still explicit.

It’s not explicit in the sense that nobody wrote `fatalError` or similar in 
their code.  It’s too easy to write something like that without realizing that 
it introduces the possibility of a crash.  If we adopt syntax like that to 
introduce an existential that introduces traps we should at least require 
members that can be trap to be invoked using a `!` suffix or something like 
that to make it clear to users that a trap will happen if they are not 
extremely careful when using that member.  

More generally though, I don’t want the rules of the language to be written in 
a way that causes the compiler to synthesize traps in such 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Dave Abrahams via swift-evolution

on Wed Jun 08 2016, Austin Zheng  wrote:

> On Wed, Jun 8, 2016 at 3:22 PM, Dave Abrahams  wrote:
>
>>
>> on Wed Jun 08 2016, Austin Zheng  wrote:
>>
>> > FWIW my opinion is that existentials either shouldn't be allowed to stand
>> > in for generic type parameters, or Dave's option #1 if they are.
>>
>> Don't you mean #2?  Otherwise I'm confused.  #1 is the one that
>> prohibits more usages.
>>
>
> I'm just being cautious until a better solution comes along.
>
>>
>> > The implied promise of a generic type parameter T right now is that T
>> > always stands for the same concrete type (modulo things like passing
>> > in a subclass where a class would do), and likewise for all of T's
>> > associated types (T.Foo is always the same type everywhere in the
>> > context where T is valid). This is what makes using anything with
>> > 'self' requirements in a generic context sound. Allowing existentials
>> > to satisfy T would violate that constraint.
>>
>> Not if you consider Any to be a
>> concrete type.  Concrete w.r.t. to a generic parameter means something
>> different from Concrete w.r.t. subtyping.
>>
>
> You can consider Any to be a concrete
> type, but then you have the unprecedented situation where the associated
> types associated with a concrete type aren't necessarily the same for all
> instances (is this true for any type that can satisfy a generic type
> parameter today?).
>
> (For the sake of this argument, Array isn't a concrete type, but Array
> or Array is. You can't use 'Array' anywhere in Swift today, so I think
> my assertion is fair.)
>
> My understanding is that fixing the generic type parameter T by
> specializing a function/type also fixes all the associated types associated
> with T. This 'contract' would have to be weakened to allow existential
> types to satisfy generic type parameters in any non-trivial way.
>
>>
>> > Relaxing these semantics would make it too easy to write code that
>> > traps at runtime "without the user having to reach" (to paraphrase
>> > Jordan from the "Swift philosophy" thread). Anyone who really really
>> > wants to write code that is 'compile-time unsound' in this way should
>> > have to explicitly type erase using concrete wrappers.
>>
>> I'd really like to see the use-cases, to make sure that these restricted
>> existentials will be useful enough to be worth implementing.
>>
>
> This is enormously important.
>
> First of all, (of course you know) there is a semantic difference between:
>
> protocol Pet : class { }; class Cat : Pet { }; class Dog : Pet { }
>
> class AnimalShelter { var pet: T }
>
> and
>
> class AnimalShelter { var pet: Pet }
>
> This is something you can express for simple existentials today (the code
> above should run, with minor modifications), but not for existentials
> containing associated types or self requirements.

Sorry, what code?  The above code runs just fine.  Maybe you mean

   typealias T = AnimalShelter

?

> I think a big part of what people want to do is to declare variables, pass
> args to functions, and get return values from functions that abstract over
> something like Collection. They want to do this without having to make
> their code generic, and without forcing their code to be homogenous at
> runtime (e.g. an instance of the dynamic AnimalShelter can be populated
> with a cat and later a dog, but the generic one can only ever contain
> either; extend this to Collections of Ints or whatnot).
>
> The big problem is that existentials can't guarantee that they satisfy the
> contract generic functions and types are expecting, as we've been
> discussing.
>
> To be honest, I think requiring existentials to be opened should be a
> prerequisite to using them generically. 

It's a reasonable approach.

> This would define away the impedance mismatch at the expense of making
> certain things marginally harder to do. (An alternate way of thinking
> about it is that it would make the potential for a runtime error
> explicit, and localize it):
>
> func doSomething(x: C, y: C) { ... }
>
> let a : Any
> let b : Any
>
> // Prohibit this...
> // doSomething(a, b)
>
> // Allow this:
> if let a = a openas? T, b = b as? T {
>   // We've recovered the 'strong guarantee' that doSomething expects for T
>   doSomething(a, b)
> } else {
>   // Here's our trap
> }
>
> The biggest problem is that this sort of solution would prohibit
> existentials from being used in generic contexts where the existentials
> only have to be "similar enough", not identical, for things to work out.
> Given how fuzzy "similar enough" has proven to be, maybe that's not a
> terrible tradeoff.

Maybe not.  More info is needed, is all I'm saying.

>> >
>> >
>> > Best,
>> > Austin
>> >
>> > On Wed, Jun 8, 2016 at 2:37 PM, Austin Zheng 
>> wrote:
>> >
>> >> We might be talking past each other. I think Matthew is talking about
>> >> using an existential outside the context of generic functions. For
>> example,
>> >> something 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Dave Abrahams via swift-evolution

on Wed Jun 08 2016, Matthew Johnson  wrote:

>> On Jun 8, 2016, at 1:33 PM, Dave Abrahams  wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson  wrote:
>> 
>
 On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson >>> > wrote:
 
>>> 
>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>>  wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson  wrote:
>> 
> 
 , but haven't realized
 that if you step around the type relationships encoded in Self
 requirements and associated types you end up with types that appear to
 interoperate but in fact trap at runtime unless used in exactly the
 right way.
>>> 
>>> Trap at runtime?  How so?  Generalized existentials should still be
>>> type-safe.  
>> 
>> There are two choices when you erase static type relationships:
>> 
>> 1. Acheive type-safety by trapping at runtime
>> 
>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>> 
>> 2. Don't expose protocol requirements that involve these relationships,
>> which would prevent the code above from compiling and prevent
>> FloatingPoint from conforming to itself.
>> 
>>> Or are you talking about the hypothetical types / behaviors people
>>> think they want when they don’t fully understand what is happening...
>> 
>> I don't know what you mean here.  I think generalized existentials will
>> be nice to have, but I think most people will want them to do something
>> they can't possibly do.
> 
> Exactly.  What I meant is that people think they want that expression
> to compile because they don’t understand that the only thing it can do
> is trap.  I said “hypothetical” because producing a compile time error
> rather than a runtime trap is the only sane thing to do.  Your comment
> surprised me because I can’t imagine we would move forward in Swift
> with the approach of trapping.
 
 I would very much like to be able to create instances of “Collection
 where Element == Int” so we can throw away the wrappers in the stdlib.
 That will require some type mismatches to be caught at runtime via
 trapping.
>>> 
>>> For invalid index because the existential accepts a type erased index?
>> 
>> Exactly.
>> 
>>> How do you decide where to draw the line here?  It feels like a very
>>> slippery slope for a language where safety is a stated priority to
>>> start adopting a strategy of runtime trapping for something as
>>> fundamental as how you expose members on an existential.
>> 
>> If you don't do this, the alternative is that “Collection where Element
>> == Int” does not conform to Collection.  
>
> This isn’t directly related to having self or associated type
> requirements.  It is true of all existentials.  

That is just an implementation limitation today, IIUC.  What I'm talking
about here would make it impossible for some to do that.

> If that changes for simple existentials and generalized existentials
> expose all members (as in the latest draft of the proposal) maybe it
> will be possible for all existentials to conform to their protocol.

Not without introducing runtime traps.  See my “subscript function”
example.

>
>> That's weird and not very
>> useful.  You could expose all the methods that were on protocol
>> extensions of Collection on this existential, unless they used
>> associated types other than the element type.  But you couldn't pass the
>> existential to a generic function like
>> 
>>   func scrambled(_ c: C) -> [C.Element]
>> 
>>> IMO you should *have* to introduce unsafe behavior like that manually.
>> 
>>  Collection where Element == Int & Index == *
>> 
>> ?
>
> I didn’t mean directly through the type of the existential.

My question is, why not?  That is still explicit.

> One obvious mechanism for introducing unsafe behavior is to write
> manual type erasure wrappers like we do today.
>
> Another possibility would be to allow extending the existential type
> (not the protocol).  This would allow you to write overloads on the
> Collection existential that takes some kind of type erased index if
> that is what you want and either trap if you receive an invalid index
> or better (IMO) return an `Element?`.  I’m not sure how extensions on
> existentials might be implemented, but this is an example of the kind
> of operation you might want available on it that you wouldn’t want
> available on all Collection types.
>
>> 
>>> Collection indices are already something that isn’t fully statically
>>> safe so I understand why you might want to allow this.  
>> 
>> By the same measure, so are Ints :-)
>> 
>> The fact that a type's methods have preconditions does *not* make it
>> “statically unsafe.”
>
> That 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Austin Zheng via swift-evolution

> On Jun 8, 2016, at 11:52 PM, Russ Bishop  wrote:
> 
>> 
>> On Jun 8, 2016, at 3:18 PM, Dave Abrahams via swift-evolution 
>> > wrote:
>> 
>> Exactly.  But much simpler cases will also either have to trap at
>> runtime or be prohibited outright:
>> 
>>  func subscript_(c: C, i: C.Index) -> C.Collection.Element {
>>return c[i]
>>  }
>> 
>>  typealias IntCollection = Any
>>  let c1: IntCollection = ...
>>  let c2: IntCollection = c1[3..<10]
>>  let c3: IntCollection = ...
>>  let c4: IntCollection = c1.reversed()
>> 
>>  // Note: the underlying index types are the same, and are supposed to
>>  // interoperate.  What do you do (work/trap/nocompile)?
>>  _ = subscript_(c1, c2.startIndex)
>> 
>>  // The underlying index types happen to be the same, and are not
>>  // supposed to interoperate.  What do you do (silently 
>> “work”/trap/nocompile)?
>>  _ = subscript_(c1, c3.startIndex)
>> 
>>  // The underlying index types are different.  What do you do 
>> (trap/nocompile)?
>>  _ = subscript_(c1, c4.startIndex)
>> 
>> -- 
>> Dave
> 
> Is it sufficient to say that unconstrained associated types cannot satisfy 
> generic constraints so subscript_ can’t be called with startIndex? 
> Presumably if you said Any you 
> could then call subscript_.

Presumably, if a type was of existential type but all its associated types were 
constrained to concrete types and none contain Self requirements, you should be 
able to use it to satisfy a generic parameter. (Self requirements are still a 
problem. `Equatable` has no associated types, but you'd still run into problems 
using that existential in a generic context.)

Practically speaking, this wouldn't be too useful for most complex protocols. 
Swift 3's `Collection` defines at least `SubSequence`, `Indices`, `Index` (I 
think), and `Iterator`, all of which would have to be bound to meet this 
requirement. Then you get into recursive associated type constraints...

> 
> Not being a compiler expert another thought occurs to me: Can the type of an 
> existential/unconstrained associated type be an unique anonymous type in the 
> local scope? In this case c1.startIndex is of type a’; it cannot be stored in 
> a global, passed to another function, etc. It is only usable in the current 
> scope for interacting with c1. c2.startIndex would be of type b’, etc. This 
> is similar to how anonymous types work in C#. The issues with func(a: X, 
> b: X) could in theory be solved the same way: require opening the existential 
> in the local scope and validating that the actual types are identical before 
> you can call func. 

Joe Groff thinks it's possible. I wrote something up along those lines here: 
https://github.com/austinzheng/swift-evolution/blob/az-existentials/proposals/-enhanced-existentials.md#associated-types-and-member-exposure
 

> 
> In that sense you could say the types are really:
> 
> let c1: a’
> let c2: b’
> let c3: c’
> let c4: d’
> 
> // accepts responsibility for a and b being different concrete types at 
> runtime
> func doIt(a: IntCollection, b: IntCollection) { }
> 
> // caller must prove a & b are same concrete type
> func makeIt(a: C, b: C) { }
> 
> 
> They are completely separate types until proven otherwise and you can’t go 
> passing them around unless the callee accepts responsibility for the dynamism 
> or you prove exactly which type you’re talking about.
> 
> (I freely admit this may be nonsensical or impossible to implement reasonably 
> in the compiler)
> 
> 
> Russ

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread L. Mihalkovic via swift-evolution

> On Jun 9, 2016, at 8:06 AM, Austin Zheng  wrote:
> 
> According to that code (which is in Decl.cpp), AnyObject (and Any) conforms 
> to itself; no non-@objc protocol is allowed to conform to itself. An @objc 
> protocol may or may not conform to itself, depending on some other conditions.

Like I said... more sub-cases than your original statement, right?!

> 
>> On Jun 8, 2016, at 9:19 PM, L. Mihalkovic  
>> wrote:
>> 
>> 
>> 
>> On Jun 8, 2016, at 9:43 PM, Austin Zheng via swift-evolution 
>>  wrote:
>> 
>>> It's not possible, even with Swift's current implementation of 
>>> existentials. A protocol type P isn't considered to conform to itself, thus 
>>> the following is rejected:
>> 
>> The rules are not that simple, I seem to recall reading in sourcecode that 
>> there are criteria that decide if that is true or not. And by default the 
>> variable conform_to_self is even TRUE
>> 
>> 
>>> 
>>> let a : MyProtocol = // ...
>>> func myFunc(x: T) {
>>>   // 
>>> }
>>> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type 
>>> MyProtocol"
>>> 
>>> Changing how this works is probably worth a proposal by itself.
>>> 
>>> Austin
>>> 
>>> 
 On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution 
  wrote:
 
 > Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution 
 > :
 >
 >
 > on Tue Jun 07 2016, Matthew Johnson  wrote:
 >
 >>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
 >>>
 >>>
 >>> on Tue Jun 07 2016, Matthew Johnson >>> >>> > wrote:
 >>>
 >>
 > On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
 >  wrote:
 >
 >
 > on Tue Jun 07 2016, Matthew Johnson  
 > wrote:
 >
 
 >>> , but haven't realized
 >>> that if you step around the type relationships encoded in Self
 >>> requirements and associated types you end up with types that 
 >>> appear to
 >>> interoperate but in fact trap at runtime unless used in exactly the
 >>> right way.
 >>
 >> Trap at runtime?  How so?  Generalized existentials should still be
 >> type-safe.
 >
 > There are two choices when you erase static type relationships:
 >
 > 1. Acheive type-safety by trapping at runtime
 >
 > FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
 >
 > 2. Don't expose protocol requirements that involve these 
 > relationships,
 > which would prevent the code above from compiling and prevent
 > FloatingPoint from conforming to itself.
 >
 >> Or are you talking about the hypothetical types / behaviors people
 >> think they want when they don’t fully understand what is 
 >> happening...
 >
 > I don't know what you mean here.  I think generalized existentials 
 > will
 > be nice to have, but I think most people will want them to do 
 > something
 > they can't possibly do.
 
  Exactly.  What I meant is that people think they want that expression
  to compile because they don’t understand that the only thing it can do
  is trap.  I said “hypothetical” because producing a compile time error
  rather than a runtime trap is the only sane thing to do.  Your comment
  surprised me because I can’t imagine we would move forward in Swift
  with the approach of trapping.
 >>>
 >>> I would very much like to be able to create instances of “Collection
 >>> where Element == Int” so we can throw away the wrappers in the stdlib.
 >>> That will require some type mismatches to be caught at runtime via
 >>> trapping.
 >>
 >> For invalid index because the existential accepts a type erased index?
 >
 > Exactly.
 >
 >> How do you decide where to draw the line here?  It feels like a very
 >> slippery slope for a language where safety is a stated priority to
 >> start adopting a strategy of runtime trapping for something as
 >> fundamental as how you expose members on an existential.
 >
 > If you don't do this, the alternative is that “Collection where Element
 > == Int” does not conform to Collection.  That's weird and not very
 > useful.  You could expose all the methods that were on protocol
 > extensions of Collection on this existential, unless they used
 > associated types other than the element type.  But you couldn't pass the
 > existential to a generic function like
 >
 >   func scrambled(_ c: C) -> [C.Element]
 
 I don’t understand. Why couldn’t an 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Russ Bishop via swift-evolution

> On Jun 8, 2016, at 3:18 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> Exactly.  But much simpler cases will also either have to trap at
> runtime or be prohibited outright:
> 
>  func subscript_(c: C, i: C.Index) -> C.Collection.Element {
>return c[i]
>  }
> 
>  typealias IntCollection = Any
>  let c1: IntCollection = ...
>  let c2: IntCollection = c1[3..<10]
>  let c3: IntCollection = ...
>  let c4: IntCollection = c1.reversed()
> 
>  // Note: the underlying index types are the same, and are supposed to
>  // interoperate.  What do you do (work/trap/nocompile)?
>  _ = subscript_(c1, c2.startIndex)
> 
>  // The underlying index types happen to be the same, and are not
>  // supposed to interoperate.  What do you do (silently 
> “work”/trap/nocompile)?
>  _ = subscript_(c1, c3.startIndex)
> 
>  // The underlying index types are different.  What do you do 
> (trap/nocompile)?
>  _ = subscript_(c1, c4.startIndex)
> 
> -- 
> Dave

Is it sufficient to say that unconstrained associated types cannot satisfy 
generic constraints so subscript_ can’t be called with startIndex? 
Presumably if you said Any you 
could then call subscript_.

Not being a compiler expert another thought occurs to me: Can the type of an 
existential/unconstrained associated type be an unique anonymous type in the 
local scope? In this case c1.startIndex is of type a’; it cannot be stored in a 
global, passed to another function, etc. It is only usable in the current scope 
for interacting with c1. c2.startIndex would be of type b’, etc. This is 
similar to how anonymous types work in C#. The issues with func(a: X, b: X) 
could in theory be solved the same way: require opening the existential in the 
local scope and validating that the actual types are identical before you can 
call func. 

In that sense you could say the types are really:

let c1: a’
let c2: b’
let c3: c’
let c4: d’

// accepts responsibility for a and b being different concrete types at runtime
func doIt(a: IntCollection, b: IntCollection) { }

// caller must prove a & b are same concrete type
func makeIt(a: C, b: C) { }


They are completely separate types until proven otherwise and you can’t go 
passing them around unless the callee accepts responsibility for the dynamism 
or you prove exactly which type you’re talking about.

(I freely admit this may be nonsensical or impossible to implement reasonably 
in the compiler)


Russ


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-09 Thread Austin Zheng via swift-evolution
According to that code (which is in Decl.cpp), AnyObject (and Any) conforms to 
itself; no non-@objc protocol is allowed to conform to itself. An @objc 
protocol may or may not conform to itself, depending on some other conditions.

> On Jun 8, 2016, at 9:19 PM, L. Mihalkovic  
> wrote:
> 
> 
> 
> On Jun 8, 2016, at 9:43 PM, Austin Zheng via swift-evolution 
> > wrote:
> 
>> It's not possible, even with Swift's current implementation of existentials. 
>> A protocol type P isn't considered to conform to itself, thus the following 
>> is rejected:
> 
> The rules are not that simple, I seem to recall reading in sourcecode that 
> there are criteria that decide if that is true or not. And by default the 
> variable conform_to_self is even TRUE
> 
> 
>> 
>> let a : MyProtocol = // ...
>> func myFunc(x: T) {
>>   // 
>> }
>> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type 
>> MyProtocol"
>> 
>> Changing how this works is probably worth a proposal by itself.
>> 
>> Austin
>> 
>> 
>> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>> > Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution 
>> > >:
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson > > > wrote:
>> >
>> >>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams > >>> > wrote:
>> >>>
>> >>>
>> >>> on Tue Jun 07 2016, Matthew Johnson > >>>  > >>> >> wrote:
>> >>>
>> >>
>> > On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>> > > wrote:
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson > > > wrote:
>> >
>> 
>> >>> , but haven't realized
>> >>> that if you step around the type relationships encoded in Self
>> >>> requirements and associated types you end up with types that appear 
>> >>> to
>> >>> interoperate but in fact trap at runtime unless used in exactly the
>> >>> right way.
>> >>
>> >> Trap at runtime?  How so?  Generalized existentials should still be
>> >> type-safe.
>> >
>> > There are two choices when you erase static type relationships:
>> >
>> > 1. Acheive type-safety by trapping at runtime
>> >
>> > FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>> >
>> > 2. Don't expose protocol requirements that involve these relationships,
>> > which would prevent the code above from compiling and prevent
>> > FloatingPoint from conforming to itself.
>> >
>> >> Or are you talking about the hypothetical types / behaviors people
>> >> think they want when they don’t fully understand what is happening...
>> >
>> > I don't know what you mean here.  I think generalized existentials will
>> > be nice to have, but I think most people will want them to do something
>> > they can't possibly do.
>> 
>>  Exactly.  What I meant is that people think they want that expression
>>  to compile because they don’t understand that the only thing it can do
>>  is trap.  I said “hypothetical” because producing a compile time error
>>  rather than a runtime trap is the only sane thing to do.  Your comment
>>  surprised me because I can’t imagine we would move forward in Swift
>>  with the approach of trapping.
>> >>>
>> >>> I would very much like to be able to create instances of “Collection
>> >>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> >>> That will require some type mismatches to be caught at runtime via
>> >>> trapping.
>> >>
>> >> For invalid index because the existential accepts a type erased index?
>> >
>> > Exactly.
>> >
>> >> How do you decide where to draw the line here?  It feels like a very
>> >> slippery slope for a language where safety is a stated priority to
>> >> start adopting a strategy of runtime trapping for something as
>> >> fundamental as how you expose members on an existential.
>> >
>> > If you don't do this, the alternative is that “Collection where Element
>> > == Int” does not conform to Collection.  That's weird and not very
>> > useful.  You could expose all the methods that were on protocol
>> > extensions of Collection on this existential, unless they used
>> > associated types other than the element type.  But you couldn't pass the
>> > existential to a generic function like
>> >
>> >   func scrambled(_ c: C) -> [C.Element]
>> 
>> I don’t understand. Why couldn’t an existential be passed to that function?
>> 
>> -Thorsten
>> 
>> 
>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread L. Mihalkovic via swift-evolution


> On Jun 9, 2016, at 12:49 AM, Austin Zheng via swift-evolution 
>  wrote:
> 
> 
> 
>> On Wed, Jun 8, 2016 at 3:22 PM, Dave Abrahams  wrote:
>> 
>> on Wed Jun 08 2016, Austin Zheng  wrote:
>> 
>> > FWIW my opinion is that existentials either shouldn't be allowed to stand
>> > in for generic type parameters, or Dave's option #1 if they are.
>> 
>> Don't you mean #2?  Otherwise I'm confused.  #1 is the one that
>> prohibits more usages.
> 
> I'm just being cautious until a better solution comes along.
>  
>> 
>> > The implied promise of a generic type parameter T right now is that T
>> > always stands for the same concrete type (modulo things like passing
>> > in a subclass where a class would do), and likewise for all of T's
>> > associated types (T.Foo is always the same type everywhere in the
>> > context where T is valid). This is what makes using anything with
>> > 'self' requirements in a generic context sound. Allowing existentials
>> > to satisfy T would violate that constraint.
>> 
>> Not if you consider Any to be a
>> concrete type.  Concrete w.r.t. to a generic parameter means something
>> different from Concrete w.r.t. subtyping.
> 
> You can consider Any to be a concrete type, 
> but then you have the unprecedented situation where the associated types 
> associated with a concrete type aren't necessarily the same for all instances 
> (is this true for any type that can satisfy a generic type parameter today?).
> 
> (For the sake of this argument, Array isn't a concrete type, but Array or 
> Array is. You can't use 'Array' anywhere in Swift today, so I think my 
> assertion is fair.)
> 
> My understanding is that fixing the generic type parameter T by specializing 
> a function/type also fixes all the associated types associated with T. This 
> 'contract' would have to be weakened to allow existential types to satisfy 
> generic type parameters in any non-trivial way.
>  
>> 
>> > Relaxing these semantics would make it too easy to write code that
>> > traps at runtime "without the user having to reach" (to paraphrase
>> > Jordan from the "Swift philosophy" thread). Anyone who really really
>> > wants to write code that is 'compile-time unsound' in this way should
>> > have to explicitly type erase using concrete wrappers.
>> 
>> I'd really like to see the use-cases, to make sure that these restricted
>> existentials will be useful enough to be worth implementing.
> 
> This is enormously important.
> 
> First of all, (of course you know) there is a semantic difference between:
> 
> protocol Pet : class { }; class Cat : Pet { }; class Dog : Pet { }
> 
> class AnimalShelter { var pet: T }
> 
> and 
> 
> class AnimalShelter { var pet: Pet }
> 
> This is something you can express for simple existentials today (the code 
> above should run, with minor modifications), but not for existentials 
> containing associated types or self requirements.
> 
> I think a big part of what people want to do is to declare variables, pass 
> args to functions, and get return values from functions that abstract over 
> something like Collection. They want to do this without having to make their 
> code generic, and without forcing their code to be homogenous at runtime 
> (e.g. an instance of the dynamic AnimalShelter can be populated with a cat 
> and later a dog, but the generic one can only ever contain either; extend 
> this to Collections of Ints or whatnot).
> 
> The big problem is that existentials can't guarantee that they satisfy the 
> contract generic functions and types are expecting, as we've been discussing.
> 
> To be honest, I think requiring existentials to be opened should be a 
> prerequisite to using them generically. This would define away the impedance 
> mismatch at the expense of making certain things marginally harder to do. (An 
> alternate way of thinking about it is that it would make the potential for a 
> runtime error explicit, and localize it):
> 
> func doSomething(x: C, y: C) { ... }
> 
> let a : Any
> let b : Any
> 
> // Prohibit this...
> // doSomething(a, b)
> 
> // Allow this:
> if let a = a openas? T, b = b as? T {
>   // We've recovered the 'strong guarantee' that doSomething expects for T
>   doSomething(a, b)
> } else {
>   // Here's our trap
> }

Right... exactly what I wrote yesterday, from Doug having written it months ago.

You are still missing the dynamicType checking to make invoking comparable{} 
methods work.

and that could further be simplified with something like

If letAs a:T , y:T {
   // compatible types, but still possible for dynamic types to be different
}

LetAs is a strawman for 
Let a = a openas? T

> 
> The biggest problem is that this sort of solution would prohibit existentials 
> from being used in generic contexts where the existentials only have to be 
> "similar enough", not identical, for things to work out. Given how fuzzy 
> "similar enough" has proven to be, maybe that's not a terrible 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread L. Mihalkovic via swift-evolution


> On Jun 8, 2016, at 9:43 PM, Austin Zheng via swift-evolution 
>  wrote:
> 
> It's not possible, even with Swift's current implementation of existentials. 
> A protocol type P isn't considered to conform to itself, thus the following 
> is rejected:

The rules are not that simple, I seem to recall reading in sourcecode that 
there are criteria that decide if that is true or not. And by default the 
variable conform_to_self is even TRUE


> 
> let a : MyProtocol = // ...
> func myFunc(x: T) {
>   // 
> }
> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type MyProtocol"
> 
> Changing how this works is probably worth a proposal by itself.
> 
> Austin
> 
> 
>> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution 
>>  wrote:
>> 
>> > Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution 
>> > :
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson  wrote:
>> >
>> >>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
>> >>>
>> >>>
>> >>> on Tue Jun 07 2016, Matthew Johnson > >>> > wrote:
>> >>>
>> >>
>> > On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>> >  wrote:
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson  wrote:
>> >
>> 
>> >>> , but haven't realized
>> >>> that if you step around the type relationships encoded in Self
>> >>> requirements and associated types you end up with types that appear 
>> >>> to
>> >>> interoperate but in fact trap at runtime unless used in exactly the
>> >>> right way.
>> >>
>> >> Trap at runtime?  How so?  Generalized existentials should still be
>> >> type-safe.
>> >
>> > There are two choices when you erase static type relationships:
>> >
>> > 1. Acheive type-safety by trapping at runtime
>> >
>> > FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>> >
>> > 2. Don't expose protocol requirements that involve these relationships,
>> > which would prevent the code above from compiling and prevent
>> > FloatingPoint from conforming to itself.
>> >
>> >> Or are you talking about the hypothetical types / behaviors people
>> >> think they want when they don’t fully understand what is happening...
>> >
>> > I don't know what you mean here.  I think generalized existentials will
>> > be nice to have, but I think most people will want them to do something
>> > they can't possibly do.
>> 
>>  Exactly.  What I meant is that people think they want that expression
>>  to compile because they don’t understand that the only thing it can do
>>  is trap.  I said “hypothetical” because producing a compile time error
>>  rather than a runtime trap is the only sane thing to do.  Your comment
>>  surprised me because I can’t imagine we would move forward in Swift
>>  with the approach of trapping.
>> >>>
>> >>> I would very much like to be able to create instances of “Collection
>> >>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> >>> That will require some type mismatches to be caught at runtime via
>> >>> trapping.
>> >>
>> >> For invalid index because the existential accepts a type erased index?
>> >
>> > Exactly.
>> >
>> >> How do you decide where to draw the line here?  It feels like a very
>> >> slippery slope for a language where safety is a stated priority to
>> >> start adopting a strategy of runtime trapping for something as
>> >> fundamental as how you expose members on an existential.
>> >
>> > If you don't do this, the alternative is that “Collection where Element
>> > == Int” does not conform to Collection.  That's weird and not very
>> > useful.  You could expose all the methods that were on protocol
>> > extensions of Collection on this existential, unless they used
>> > associated types other than the element type.  But you couldn't pass the
>> > existential to a generic function like
>> >
>> >   func scrambled(_ c: C) -> [C.Element]
>> 
>> I don’t understand. Why couldn’t an existential be passed to that function?
>> 
>> -Thorsten
>> 
>> 
>> 
>> >
>> >> IMO you should *have* to introduce unsafe behavior like that manually.
>> >
>> >  Collection where Element == Int & Index == *
>> >
>> > ?
>> >
>> >> Collection indices are already something that isn’t fully statically
>> >> safe so I understand why you might want to allow this.
>> >
>> > By the same measure, so are Ints :-)
>> >
>> > The fact that a type's methods have preconditions does *not* make it
>> > “statically unsafe.”
>> >
>> >> But I don’t think having the language's existentials do this
>> >> automatically is the right approach.  Maybe there is another approach
>> >> that could be used in targeted use cases where the less safe behavior
>> >> makes sense and is 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Austin Zheng via swift-evolution
On Wed, Jun 8, 2016 at 3:22 PM, Dave Abrahams  wrote:

>
> on Wed Jun 08 2016, Austin Zheng  wrote:
>
> > FWIW my opinion is that existentials either shouldn't be allowed to stand
> > in for generic type parameters, or Dave's option #1 if they are.
>
> Don't you mean #2?  Otherwise I'm confused.  #1 is the one that
> prohibits more usages.
>

I'm just being cautious until a better solution comes along.


>
> > The implied promise of a generic type parameter T right now is that T
> > always stands for the same concrete type (modulo things like passing
> > in a subclass where a class would do), and likewise for all of T's
> > associated types (T.Foo is always the same type everywhere in the
> > context where T is valid). This is what makes using anything with
> > 'self' requirements in a generic context sound. Allowing existentials
> > to satisfy T would violate that constraint.
>
> Not if you consider Any to be a
> concrete type.  Concrete w.r.t. to a generic parameter means something
> different from Concrete w.r.t. subtyping.
>

You can consider Any to be a concrete
type, but then you have the unprecedented situation where the associated
types associated with a concrete type aren't necessarily the same for all
instances (is this true for any type that can satisfy a generic type
parameter today?).

(For the sake of this argument, Array isn't a concrete type, but Array
or Array is. You can't use 'Array' anywhere in Swift today, so I think
my assertion is fair.)

My understanding is that fixing the generic type parameter T by
specializing a function/type also fixes all the associated types associated
with T. This 'contract' would have to be weakened to allow existential
types to satisfy generic type parameters in any non-trivial way.


>
> > Relaxing these semantics would make it too easy to write code that
> > traps at runtime "without the user having to reach" (to paraphrase
> > Jordan from the "Swift philosophy" thread). Anyone who really really
> > wants to write code that is 'compile-time unsound' in this way should
> > have to explicitly type erase using concrete wrappers.
>
> I'd really like to see the use-cases, to make sure that these restricted
> existentials will be useful enough to be worth implementing.
>

This is enormously important.

First of all, (of course you know) there is a semantic difference between:

protocol Pet : class { }; class Cat : Pet { }; class Dog : Pet { }

class AnimalShelter { var pet: T }

and

class AnimalShelter { var pet: Pet }

This is something you can express for simple existentials today (the code
above should run, with minor modifications), but not for existentials
containing associated types or self requirements.

I think a big part of what people want to do is to declare variables, pass
args to functions, and get return values from functions that abstract over
something like Collection. They want to do this without having to make
their code generic, and without forcing their code to be homogenous at
runtime (e.g. an instance of the dynamic AnimalShelter can be populated
with a cat and later a dog, but the generic one can only ever contain
either; extend this to Collections of Ints or whatnot).

The big problem is that existentials can't guarantee that they satisfy the
contract generic functions and types are expecting, as we've been
discussing.

To be honest, I think requiring existentials to be opened should be a
prerequisite to using them generically. This would define away the
impedance mismatch at the expense of making certain things marginally
harder to do. (An alternate way of thinking about it is that it would make
the potential for a runtime error explicit, and localize it):

func doSomething(x: C, y: C) { ... }

let a : Any
let b : Any

// Prohibit this...
// doSomething(a, b)

// Allow this:
if let a = a openas? T, b = b as? T {
  // We've recovered the 'strong guarantee' that doSomething expects for T
  doSomething(a, b)
} else {
  // Here's our trap
}

The biggest problem is that this sort of solution would prohibit
existentials from being used in generic contexts where the existentials
only have to be "similar enough", not identical, for things to work out.
Given how fuzzy "similar enough" has proven to be, maybe that's not a
terrible tradeoff.


>
> >
> >
> > Best,
> > Austin
> >
> > On Wed, Jun 8, 2016 at 2:37 PM, Austin Zheng 
> wrote:
> >
> >> We might be talking past each other. I think Matthew is talking about
> >> using an existential outside the context of generic functions. For
> example,
> >> something like this should be trap-proof (as long as 'x' is immutable,
> >> which it is in this example):
> >>
> >> func copySequenceIntoArray(x: Any >> Int>) -> [Int] {
> >> var buffer : [Int] = []
> >> // Stupid implementation to make a point
> >> var iterator : x.Iterator = x.makeIterator()
> >> while true {
> >> let nextItem : Int? = iterator.next()
> >> if let nextItem = nextItem {
> >> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Austin Zheng via swift-evolution
(inline)

On Wed, Jun 8, 2016 at 3:18 PM, Dave Abrahams  wrote:

>
> on Wed Jun 08 2016, Austin Zheng  wrote:
>
> > We might be talking past each other. I think Matthew is talking about
> using
> > an existential outside the context of generic functions. For example,
> > something like this should be trap-proof (as long as 'x' is immutable,
> > which it is in this example):
>
> [Ugh, Austin, your mail program is stripping the tabs out of the
> plaintext part so the indendation is lost.  Grabbing from browser...]
>

Sorry! I'm using gmail in the browser. I'll stay away from tabs...


>
> > func copySequenceIntoArray(x: Any Int>) -> [Int] {
> >   var buffer : [Int] = []
> > // Stupid implementation to make a point
> >   var iterator : x.Iterator = x.makeIterator()
> >   while true {
> >   let nextItem : Int? = iterator.next()
> >   if let nextItem = nextItem {
> >   buffer.append(nextItem)
> >   } else {
> >   return buffer
> >   }
> >   }
> > }
>
> Presumably this would “work” as well?
>
>   typealias IntSequence = Any
>   func f(x: IntSequence, y: IntSequence) {
> var i = x.makeIterator()
> i = y.makeIterator() // <== NO TRAP HERE, EVER.
>   }
>

This presumably wouldn't compile. The sort-of-dependent-type "x.Iterator"
(return value of x.makeIterator(); inferred as type of 'i'), and
"y.Iterator" (return type of y.makeIterator()) would not be considered
equivalent.

(As Doug mentioned in a recent email, it would only be feasible to expose
such types on immutable values. The intention is not to allow the
largely-meaningless code that follows:

func f(x: IntSequence, y: IntSequence) {
  var z : IntSequence = x
  var something : z.Iterator = x.makeIterator()
  z = y
  something = y.makeIterator()
  // ...
}
)


>
> > Even this would never trap as well:
> >
> > func copySequenceIntoArray(x: Any T>) -> [T] {
> >   var buffer : [T] = []
> >   for item in x {
> >   buffer.append(item)
> >   }
> >   return buffer
> > }
>
> Sure, this one is simple because the associated type is never even
> exposed.
>
> > Where we run into difficulty is something like this (forgive my abuse
> > of the collections API; I don't remember all the new indexing APIs off
> > the top of my head):
> >
> > func doSomething(x: T, y: T) {
> >   // Get indexes out of x and use them to index into y
> >   var idx = x.startIndex
> >   while (idx != x.endIndex || idx != y.endIndex) {
> >   print(x[idx])
> >   print(y[idx])
> >   idx = x.nextIndex(idx)
> >   }
> > }
> > let someSeq : Any = // ...
> > let anotherSeq : Any = // ...
> > // Trouble!
> > // someSeq and anotherSeq are the same existential type
> > // But the concrete index types within each of the existential variables
> may be different
> > doSomething(someSeq, anotherSeq)
> >
> > may be different
> > doSomething(someSeq, anotherSeq)
> >
> > It's this situation (using an existential type to fulfill a generic
> > type parameter constrained to the same requirements that comprise that
> > existential) that requires either of the two options that Dave
> > presented, due to our lack of compile-time type information about the
> > fulfilling type's associated types.
>
> Exactly.  But much simpler cases will also either have to trap at
> runtime or be prohibited outright:
>

Of course. I don't know what the right solution to this is yet.


>
>   func subscript_(c: C, i: C.Index) -> C.Collection.Element
> {
> return c[i]
>   }
>
>   typealias IntCollection = Any
>   let c1: IntCollection = ...
>   let c2: IntCollection = c1[3..<10]
>   let c3: IntCollection = ...
>   let c4: IntCollection = c1.reversed()
>
>   // Note: the underlying index types are the same, and are supposed to
>   // interoperate.  What do you do (work/trap/nocompile)?
>   _ = subscript_(c1, c2.startIndex)
>
>   // The underlying index types happen to be the same, and are not
>   // supposed to interoperate.  What do you do (silently
> “work”/trap/nocompile)?
>   _ = subscript_(c1, c3.startIndex)
>
>   // The underlying index types are different.  What do you do
> (trap/nocompile)?
>   _ = subscript_(c1, c4.startIndex)
>
> --
> Dave
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Dave Abrahams via swift-evolution

on Wed Jun 08 2016, Austin Zheng  wrote:

> FWIW my opinion is that existentials either shouldn't be allowed to stand
> in for generic type parameters, or Dave's option #1 if they are.

Don't you mean #2?  Otherwise I'm confused.  #1 is the one that
prohibits more usages.

> The implied promise of a generic type parameter T right now is that T
> always stands for the same concrete type (modulo things like passing
> in a subclass where a class would do), and likewise for all of T's
> associated types (T.Foo is always the same type everywhere in the
> context where T is valid). This is what makes using anything with
> 'self' requirements in a generic context sound. Allowing existentials
> to satisfy T would violate that constraint.

Not if you consider Any to be a
concrete type.  Concrete w.r.t. to a generic parameter means something
different from Concrete w.r.t. subtyping.

> Relaxing these semantics would make it too easy to write code that
> traps at runtime "without the user having to reach" (to paraphrase
> Jordan from the "Swift philosophy" thread). Anyone who really really
> wants to write code that is 'compile-time unsound' in this way should
> have to explicitly type erase using concrete wrappers.

I'd really like to see the use-cases, to make sure that these restricted
existentials will be useful enough to be worth implementing.

>
>
> Best,
> Austin
>
> On Wed, Jun 8, 2016 at 2:37 PM, Austin Zheng  wrote:
>
>> We might be talking past each other. I think Matthew is talking about
>> using an existential outside the context of generic functions. For example,
>> something like this should be trap-proof (as long as 'x' is immutable,
>> which it is in this example):
>>
>> func copySequenceIntoArray(x: Any> Int>) -> [Int] {
>> var buffer : [Int] = []
>> // Stupid implementation to make a point
>> var iterator : x.Iterator = x.makeIterator()
>> while true {
>> let nextItem : Int? = iterator.next()
>> if let nextItem = nextItem {
>> buffer.append(nextItem)
>> } else {
>> return buffer
>> }
>> }
>> }
>>
>> Even this would never trap as well:
>>
>> func copySequenceIntoArray(x: Any> T>) -> [T] {
>> var buffer : [T] = []
>> for item in x {
>> buffer.append(item)
>> }
>> return buffer
>> }
>>
>> Where we run into difficulty is something like this (forgive my abuse of
>> the collections API; I don't remember all the new indexing APIs off the top
>> of my head):
>>
>> func doSomething(x: T, y: T) {
>> // Get indexes out of x and use them to index into y
>> var idx = x.startIndex
>> while (idx != x.endIndex || idx != y.endIndex) {
>> print(x[idx])
>> print(y[idx])
>> idx = x.nextIndex(idx)
>> }
>> }
>> let someSeq : Any = // ...
>> let anotherSeq : Any = // ...
>> // Trouble!
>> // someSeq and anotherSeq are the same existential type
>> // But the concrete index types within each of the existential variables
>> may be different
>> doSomething(someSeq, anotherSeq)
>>
>> It's this situation (using an existential type to fulfill a generic type
>> parameter constrained to the same requirements that comprise that
>> existential) that requires either of the two options that Dave presented,
>> due to our lack of compile-time type information about the fulfilling
>> type's associated types.
>>
>> Best,
>> Austin
>>
>> On Wed, Jun 8, 2016 at 2:33 PM, Matthew Johnson via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>>
>>> Sent from my iPad
>>>
>>> > On Jun 8, 2016, at 3:16 PM, Dave Abrahams via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>> >
>>> >
>>> >> on Wed Jun 08 2016, Thorsten Seitz  wrote:
>>> >>
>>> >> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>>> >> to read up again what the reasons are for that behavior).
>>> >
>>> > Yes, but in the case of the issue we're discussing, the choices are:
>>> >
>>> > 1. Omit from the existential's API any protocol requirements that depend
>>> >   on Self or associated types, in which case it *can't* conform to
>>> >   itself because it doesn't fulfill the requirements.
>>>
>>> They don't need to be omitted.  They are exposed in different ways
>>> depending on how the existential is constrained.  Austin's proposal was
>>> originally written to omit some members but it was modified based on
>>> feedback from Doug Gregor IIRC (Austin, is that right?).  Now it contains
>>> examples showing how these members are made available in a safe way.   Some
>>> members may still not be usable because you can't form an argument but IIRC
>>> the suggestion was that they be exposed anyway for consistency.
>>>
>>> >
>>> > 2. Erase type relationships and trap at runtime when they don't line up.
>>> >
>>> > Matthew has been arguing against #2, but you can't “fix the bug” without
>>> > it.
>>> >
>>> >>
>>> >> -Thorsten
>>> >>
>>> >>> Am 08.06.2016 um 21:43 schrieb Austin Zheng :
>>> >>>
>>> >>> It's not possible, even with Swift's current implementation of
>>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Dave Abrahams via swift-evolution

on Wed Jun 08 2016, Austin Zheng  wrote:

> We might be talking past each other. I think Matthew is talking about using
> an existential outside the context of generic functions. For example,
> something like this should be trap-proof (as long as 'x' is immutable,
> which it is in this example):

[Ugh, Austin, your mail program is stripping the tabs out of the
plaintext part so the indendation is lost.  Grabbing from browser...]

> func copySequenceIntoArray(x: Any) 
> -> [Int] {
>   var buffer : [Int] = []
> // Stupid implementation to make a point
>   var iterator : x.Iterator = x.makeIterator()
>   while true {
>   let nextItem : Int? = iterator.next()
>   if let nextItem = nextItem {
>   buffer.append(nextItem)
>   } else {
>   return buffer
>   }
>   }
> }

Presumably this would “work” as well?

  typealias IntSequence = Any
  func f(x: IntSequence, y: IntSequence) {
var i = x.makeIterator()
i = y.makeIterator() // <== NO TRAP HERE, EVER.
  }

> Even this would never trap as well:
> 
> func copySequenceIntoArray(x: Any) 
> -> [T] {
>   var buffer : [T] = []
>   for item in x {
>   buffer.append(item)
>   }
>   return buffer
> }

Sure, this one is simple because the associated type is never even
exposed.

> Where we run into difficulty is something like this (forgive my abuse
> of the collections API; I don't remember all the new indexing APIs off
> the top of my head):
> 
> func doSomething(x: T, y: T) {
>   // Get indexes out of x and use them to index into y
>   var idx = x.startIndex
>   while (idx != x.endIndex || idx != y.endIndex) {
>   print(x[idx])
>   print(y[idx])
>   idx = x.nextIndex(idx)
>   }
> }
> let someSeq : Any = // ...
> let anotherSeq : Any = // ...
> // Trouble!
> // someSeq and anotherSeq are the same existential type
> // But the concrete index types within each of the existential variables may 
> be different
> doSomething(someSeq, anotherSeq)
> 
> may be different
> doSomething(someSeq, anotherSeq)
>
> It's this situation (using an existential type to fulfill a generic
> type parameter constrained to the same requirements that comprise that
> existential) that requires either of the two options that Dave
> presented, due to our lack of compile-time type information about the
> fulfilling type's associated types.

Exactly.  But much simpler cases will also either have to trap at
runtime or be prohibited outright:

  func subscript_(c: C, i: C.Index) -> C.Collection.Element {
return c[i]
  }

  typealias IntCollection = Any
  let c1: IntCollection = ...
  let c2: IntCollection = c1[3..<10]
  let c3: IntCollection = ...
  let c4: IntCollection = c1.reversed()

  // Note: the underlying index types are the same, and are supposed to
  // interoperate.  What do you do (work/trap/nocompile)?
  _ = subscript_(c1, c2.startIndex)

  // The underlying index types happen to be the same, and are not
  // supposed to interoperate.  What do you do (silently “work”/trap/nocompile)?
  _ = subscript_(c1, c3.startIndex)

  // The underlying index types are different.  What do you do (trap/nocompile)?
  _ = subscript_(c1, c4.startIndex)

-- 
Dave
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Matthew Johnson via swift-evolution

> On Jun 8, 2016, at 4:47 PM, Austin Zheng  wrote:
> 
> FWIW my opinion is that existentials either shouldn't be allowed to stand in 
> for generic type parameters, or Dave's option #1 if they are.
> 
> The implied promise of a generic type parameter T right now is that T always 
> stands for the same concrete type (modulo things like passing in a subclass 
> where a class would do), and likewise for all of T's associated types (T.Foo 
> is always the same type everywhere in the context where T is valid). This is 
> what makes using anything with 'self' requirements in a generic context 
> sound. Allowing existentials to satisfy T would violate that constraint. 
> 
> Relaxing these semantics would make it too easy to write code that traps at 
> runtime "without the user having to reach" (to paraphrase Jordan from the 
> "Swift philosophy" thread). Anyone who really really wants to write code that 
> is 'compile-time unsound' in this way should have to explicitly type erase 
> using concrete wrappers.

Yes, exactly.

> 
> Best,
> Austin
> 
> 
> On Wed, Jun 8, 2016 at 2:37 PM, Austin Zheng  > wrote:
> We might be talking past each other. I think Matthew is talking about using 
> an existential outside the context of generic functions. For example, 
> something like this should be trap-proof (as long as 'x' is immutable, which 
> it is in this example):
> 
> func copySequenceIntoArray(x: Any) 
> -> [Int] {
>   var buffer : [Int] = []
> // Stupid implementation to make a point
>   var iterator : x.Iterator = x.makeIterator()
>   while true {
>   let nextItem : Int? = iterator.next()
>   if let nextItem = nextItem {
>   buffer.append(nextItem)
>   } else {
>   return buffer
>   }
>   }
> }
> 
> Even this would never trap as well:
> 
> func copySequenceIntoArray(x: Any) 
> -> [T] {
>   var buffer : [T] = []
>   for item in x {
>   buffer.append(item)
>   }
>   return buffer
> }
> 
> Where we run into difficulty is something like this (forgive my abuse of the 
> collections API; I don't remember all the new indexing APIs off the top of my 
> head):
> 
> func doSomething(x: T, y: T) {
>   // Get indexes out of x and use them to index into y
>   var idx = x.startIndex
>   while (idx != x.endIndex || idx != y.endIndex) {
>   print(x[idx])
>   print(y[idx])
>   idx = x.nextIndex(idx)
>   }
> }
> let someSeq : Any = // ...
> let anotherSeq : Any = // ...
> // Trouble!
> // someSeq and anotherSeq are the same existential type
> // But the concrete index types within each of the existential variables may 
> be different
> doSomething(someSeq, anotherSeq)
> 
> It's this situation (using an existential type to fulfill a generic type 
> parameter constrained to the same requirements that comprise that 
> existential) that requires either of the two options that Dave presented, due 
> to our lack of compile-time type information about the fulfilling type's 
> associated types.
> 
> Best,
> Austin
> 
> On Wed, Jun 8, 2016 at 2:33 PM, Matthew Johnson via swift-evolution 
> > wrote:
> 
> 
> Sent from my iPad
> 
> > On Jun 8, 2016, at 3:16 PM, Dave Abrahams via swift-evolution 
> > > wrote:
> >
> >
> >> on Wed Jun 08 2016, Thorsten Seitz  >> > wrote:
> >>
> >> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> >> to read up again what the reasons are for that behavior).
> >
> > Yes, but in the case of the issue we're discussing, the choices are:
> >
> > 1. Omit from the existential's API any protocol requirements that depend
> >   on Self or associated types, in which case it *can't* conform to
> >   itself because it doesn't fulfill the requirements.
> 
> They don't need to be omitted.  They are exposed in different ways depending 
> on how the existential is constrained.  Austin's proposal was originally 
> written to omit some members but it was modified based on feedback from Doug 
> Gregor IIRC (Austin, is that right?).  Now it contains examples showing how 
> these members are made available in a safe way.   Some members may still not 
> be usable because you can't form an argument but IIRC the suggestion was that 
> they be exposed anyway for consistency.
> 
> >
> > 2. Erase type relationships and trap at runtime when they don't line up.
> >
> > Matthew has been arguing against #2, but you can't “fix the bug” without
> > it.
> >
> >>
> >> -Thorsten
> >>
> >>> Am 08.06.2016 um 21:43 schrieb Austin Zheng  >>> >:
> >>>
> >>> It's not possible, even with Swift's current implementation of
> >>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Matthew Johnson via swift-evolution

> On Jun 8, 2016, at 1:33 PM, Dave Abrahams  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
>>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson >> > wrote:
>>> 
>> 
> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
 
>>> , but haven't realized
>>> that if you step around the type relationships encoded in Self
>>> requirements and associated types you end up with types that appear to
>>> interoperate but in fact trap at runtime unless used in exactly the
>>> right way.
>> 
>> Trap at runtime?  How so?  Generalized existentials should still be
>> type-safe.  
> 
> There are two choices when you erase static type relationships:
> 
> 1. Acheive type-safety by trapping at runtime
> 
> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
> 
> 2. Don't expose protocol requirements that involve these relationships,
> which would prevent the code above from compiling and prevent
> FloatingPoint from conforming to itself.
> 
>> Or are you talking about the hypothetical types / behaviors people
>> think they want when they don’t fully understand what is happening...
> 
> I don't know what you mean here.  I think generalized existentials will
> be nice to have, but I think most people will want them to do something
> they can't possibly do.
 
 Exactly.  What I meant is that people think they want that expression
 to compile because they don’t understand that the only thing it can do
 is trap.  I said “hypothetical” because producing a compile time error
 rather than a runtime trap is the only sane thing to do.  Your comment
 surprised me because I can’t imagine we would move forward in Swift
 with the approach of trapping.
>>> 
>>> I would very much like to be able to create instances of “Collection
>>> where Element == Int” so we can throw away the wrappers in the stdlib.
>>> That will require some type mismatches to be caught at runtime via
>>> trapping.
>> 
>> For invalid index because the existential accepts a type erased index?
> 
> Exactly.
> 
>> How do you decide where to draw the line here?  It feels like a very
>> slippery slope for a language where safety is a stated priority to
>> start adopting a strategy of runtime trapping for something as
>> fundamental as how you expose members on an existential.
> 
> If you don't do this, the alternative is that “Collection where Element
> == Int” does not conform to Collection.  

This isn’t directly related to having self or associated type requirements.  It 
is true of all existentials.  If that changes for simple existentials and 
generalized existentials expose all members (as in the latest draft of the 
proposal) maybe it will be possible for all existentials to conform to their 
protocol.  

> That's weird and not very
> useful.  You could expose all the methods that were on protocol
> extensions of Collection on this existential, unless they used
> associated types other than the element type.  But you couldn't pass the
> existential to a generic function like
> 
>   func scrambled(_ c: C) -> [C.Element]
> 
>> IMO you should *have* to introduce unsafe behavior like that manually.
> 
>  Collection where Element == Int & Index == *
> 
> ?

I didn’t mean directly through the type of the existential.

One obvious mechanism for introducing unsafe behavior is to write manual type 
erasure wrappers like we do today.  

Another possibility would be to allow extending the existential type (not the 
protocol).  This would allow you to write overloads on the Collection 
existential that takes some kind of type erased index if that is what you want 
and either trap if you receive an invalid index or better (IMO) return an 
`Element?`.  I’m not sure how extensions on existentials might be implemented, 
but this is an example of the kind of operation you might want available on it 
that you wouldn’t want available on all Collection types.

> 
>> Collection indices are already something that isn’t fully statically
>> safe so I understand why you might want to allow this.  
> 
> By the same measure, so are Ints :-)
> 
> The fact that a type's methods have preconditions does *not* make it
> “statically unsafe.”

That depends on what you mean by safe.  Sure, those methods aren’t going 
corrupt memory, but they *are* going to explicitly and intentionally crash for 
some inputs.  That doesn’t qualify as “fully safe” IMO.

> 
>> But I don’t think having the language's existentials do this
>> automatically is the right approach.  Maybe there is another approach
>> that could be used in targeted use cases where the less safe behavior
>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Dave Abrahams via swift-evolution

on Wed Jun 08 2016, Jordan Rose  wrote:

>> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution 
>>  wrote:
>> 
>> 
>> on Wed Jun 08 2016, Thorsten Seitz > > wrote:
>> 
>
>>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>>> to read up again what the reasons are for that behavior).
>> 
>> Yes, but in the case of the issue we're discussing, the choices are:
>> 
>> 1. Omit from the existential's API any protocol requirements that depend
>>   on Self or associated types, in which case it *can't* conform to
>>   itself because it doesn't fulfill the requirements.
>> 
>> 2. Erase type relationships and trap at runtime when they don't line up.
>> 
>> Matthew has been arguing against #2, but you can't “fix the bug” without
>> it.
>
> #1 has been my preference for a while as well, at least as a starting
> point. 

But as I've been suggesting, #1 may not worth generalizing existentials
for, especially considering that Doug says by a factor of 10x people who
want parameterized protocols are asking for things like Collection.

> It's possible we could also "open" the existential when it's only used
> by one parameter, i.e. the first would be legal and the second
> wouldn't:
>
> func foo(x: X) { … }
> func test(x: Any) {
>   foo(x) // okay, passes the dynamic type
> }
>
> func bar(a: X, b: X) { … }
> func test(x: Any, y: Any) {
>   bar(x, y) // illegal because x.dynamicType may be different from 
> y.dynamicType
> }
>
> (The check is not as simple as "the generic parameter is only
> mentioned once", because of constraints and such. But you get the
> idea.)

Interesting from a “completing the type system” perspective but perhaps
not very useful.  What are the use cases for this?  What you can do
with Hashable is intimately dependent on the type relationship.

We should really stop using protocols refining Equatable as an exemplar,
because that's a special case that has a special answer when the types
don't match up**. It's not representative of the general case, though.

** and any generalized Existential system we implement ought to support
   that answer!

-- 
Dave
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Austin Zheng via swift-evolution
FWIW my opinion is that existentials either shouldn't be allowed to stand
in for generic type parameters, or Dave's option #1 if they are.

The implied promise of a generic type parameter T right now is that T
always stands for the same concrete type (modulo things like passing in a
subclass where a class would do), and likewise for all of T's associated
types (T.Foo is always the same type everywhere in the context where T is
valid). This is what makes using anything with 'self' requirements in a
generic context sound. Allowing existentials to satisfy T would violate
that constraint.

Relaxing these semantics would make it too easy to write code that traps at
runtime "without the user having to reach" (to paraphrase Jordan from the
"Swift philosophy" thread). Anyone who really really wants to write code
that is 'compile-time unsound' in this way should have to explicitly type
erase using concrete wrappers.

Best,
Austin


On Wed, Jun 8, 2016 at 2:37 PM, Austin Zheng  wrote:

> We might be talking past each other. I think Matthew is talking about
> using an existential outside the context of generic functions. For example,
> something like this should be trap-proof (as long as 'x' is immutable,
> which it is in this example):
>
> func copySequenceIntoArray(x: Any Int>) -> [Int] {
> var buffer : [Int] = []
> // Stupid implementation to make a point
> var iterator : x.Iterator = x.makeIterator()
> while true {
> let nextItem : Int? = iterator.next()
> if let nextItem = nextItem {
> buffer.append(nextItem)
> } else {
> return buffer
> }
> }
> }
>
> Even this would never trap as well:
>
> func copySequenceIntoArray(x: Any T>) -> [T] {
> var buffer : [T] = []
> for item in x {
> buffer.append(item)
> }
> return buffer
> }
>
> Where we run into difficulty is something like this (forgive my abuse of
> the collections API; I don't remember all the new indexing APIs off the top
> of my head):
>
> func doSomething(x: T, y: T) {
> // Get indexes out of x and use them to index into y
> var idx = x.startIndex
> while (idx != x.endIndex || idx != y.endIndex) {
> print(x[idx])
> print(y[idx])
> idx = x.nextIndex(idx)
> }
> }
> let someSeq : Any = // ...
> let anotherSeq : Any = // ...
> // Trouble!
> // someSeq and anotherSeq are the same existential type
> // But the concrete index types within each of the existential variables
> may be different
> doSomething(someSeq, anotherSeq)
>
> It's this situation (using an existential type to fulfill a generic type
> parameter constrained to the same requirements that comprise that
> existential) that requires either of the two options that Dave presented,
> due to our lack of compile-time type information about the fulfilling
> type's associated types.
>
> Best,
> Austin
>
> On Wed, Jun 8, 2016 at 2:33 PM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>>
>> Sent from my iPad
>>
>> > On Jun 8, 2016, at 3:16 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >
>> >
>> >> on Wed Jun 08 2016, Thorsten Seitz  wrote:
>> >>
>> >> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> >> to read up again what the reasons are for that behavior).
>> >
>> > Yes, but in the case of the issue we're discussing, the choices are:
>> >
>> > 1. Omit from the existential's API any protocol requirements that depend
>> >   on Self or associated types, in which case it *can't* conform to
>> >   itself because it doesn't fulfill the requirements.
>>
>> They don't need to be omitted.  They are exposed in different ways
>> depending on how the existential is constrained.  Austin's proposal was
>> originally written to omit some members but it was modified based on
>> feedback from Doug Gregor IIRC (Austin, is that right?).  Now it contains
>> examples showing how these members are made available in a safe way.   Some
>> members may still not be usable because you can't form an argument but IIRC
>> the suggestion was that they be exposed anyway for consistency.
>>
>> >
>> > 2. Erase type relationships and trap at runtime when they don't line up.
>> >
>> > Matthew has been arguing against #2, but you can't “fix the bug” without
>> > it.
>> >
>> >>
>> >> -Thorsten
>> >>
>> >>> Am 08.06.2016 um 21:43 schrieb Austin Zheng :
>> >>>
>> >>> It's not possible, even with Swift's current implementation of
>> >>> existentials. A protocol type P isn't considered to conform to
>> >>> itself, thus the following is rejected:
>> >>>
>> >>> let a : MyProtocol = // ...
>> >>> func myFunc(x: T) {
>> >>>  // 
>> >>> }
>> >>> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type
>> MyProtocol"
>> >>>
>> >>> Changing how this works is probably worth a proposal by itself.
>> >>>
>> >>> Austin
>> >>>
>> >>>
>> >>> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution
>> >>> > >>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Austin Zheng via swift-evolution
We might be talking past each other. I think Matthew is talking about using
an existential outside the context of generic functions. For example,
something like this should be trap-proof (as long as 'x' is immutable,
which it is in this example):

func copySequenceIntoArray(x: Any)
-> [Int] {
var buffer : [Int] = []
// Stupid implementation to make a point
var iterator : x.Iterator = x.makeIterator()
while true {
let nextItem : Int? = iterator.next()
if let nextItem = nextItem {
buffer.append(nextItem)
} else {
return buffer
}
}
}

Even this would never trap as well:

func copySequenceIntoArray(x: Any) -> [T] {
var buffer : [T] = []
for item in x {
buffer.append(item)
}
return buffer
}

Where we run into difficulty is something like this (forgive my abuse of
the collections API; I don't remember all the new indexing APIs off the top
of my head):

func doSomething(x: T, y: T) {
// Get indexes out of x and use them to index into y
var idx = x.startIndex
while (idx != x.endIndex || idx != y.endIndex) {
print(x[idx])
print(y[idx])
idx = x.nextIndex(idx)
}
}
let someSeq : Any = // ...
let anotherSeq : Any = // ...
// Trouble!
// someSeq and anotherSeq are the same existential type
// But the concrete index types within each of the existential variables
may be different
doSomething(someSeq, anotherSeq)

It's this situation (using an existential type to fulfill a generic type
parameter constrained to the same requirements that comprise that
existential) that requires either of the two options that Dave presented,
due to our lack of compile-time type information about the fulfilling
type's associated types.

Best,
Austin

On Wed, Jun 8, 2016 at 2:33 PM, Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> Sent from my iPad
>
> > On Jun 8, 2016, at 3:16 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> >
> >> on Wed Jun 08 2016, Thorsten Seitz  wrote:
> >>
> >> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> >> to read up again what the reasons are for that behavior).
> >
> > Yes, but in the case of the issue we're discussing, the choices are:
> >
> > 1. Omit from the existential's API any protocol requirements that depend
> >   on Self or associated types, in which case it *can't* conform to
> >   itself because it doesn't fulfill the requirements.
>
> They don't need to be omitted.  They are exposed in different ways
> depending on how the existential is constrained.  Austin's proposal was
> originally written to omit some members but it was modified based on
> feedback from Doug Gregor IIRC (Austin, is that right?).  Now it contains
> examples showing how these members are made available in a safe way.   Some
> members may still not be usable because you can't form an argument but IIRC
> the suggestion was that they be exposed anyway for consistency.
>
> >
> > 2. Erase type relationships and trap at runtime when they don't line up.
> >
> > Matthew has been arguing against #2, but you can't “fix the bug” without
> > it.
> >
> >>
> >> -Thorsten
> >>
> >>> Am 08.06.2016 um 21:43 schrieb Austin Zheng :
> >>>
> >>> It's not possible, even with Swift's current implementation of
> >>> existentials. A protocol type P isn't considered to conform to
> >>> itself, thus the following is rejected:
> >>>
> >>> let a : MyProtocol = // ...
> >>> func myFunc(x: T) {
> >>>  // 
> >>> }
> >>> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type
> MyProtocol"
> >>>
> >>> Changing how this works is probably worth a proposal by itself.
> >>>
> >>> Austin
> >>>
> >>>
> >>> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution
> >>>  >>> >
> >>> wrote:
> >>>
>  Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution
>    >:
> 
> 
>  on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
> >> On Jun 7, 2016, at 9:15 PM, Dave Abrahams
> >>  >> >
> >> wrote:
> >>
> >>
> >> on Tue Jun 07 2016, Matthew Johnson  >>  >> >> wrote:
> >
>  On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution
>    >
>  wrote:
> 
> 
>  on Tue Jun 07 2016, Matthew Johnson
>    >
>  wrote:
> >>>
> >> , but haven't realized
> >> that if you step around the type relationships encoded in Self
> >> requirements and associated types you end up with types that
> appear to
> >> interoperate but in fact trap at runtime unless used in exactly
> the
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Jun 8, 2016, at 3:16 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
>> on Wed Jun 08 2016, Thorsten Seitz  wrote:
>> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices are:
> 
> 1. Omit from the existential's API any protocol requirements that depend
>   on Self or associated types, in which case it *can't* conform to
>   itself because it doesn't fulfill the requirements.

They don't need to be omitted.  They are exposed in different ways depending on 
how the existential is constrained.  Austin's proposal was originally written 
to omit some members but it was modified based on feedback from Doug Gregor 
IIRC (Austin, is that right?).  Now it contains examples showing how these 
members are made available in a safe way.   Some members may still not be 
usable because you can't form an argument but IIRC the suggestion was that they 
be exposed anyway for consistency.

> 
> 2. Erase type relationships and trap at runtime when they don't line up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” without
> it.
> 
>> 
>> -Thorsten
>> 
>>> Am 08.06.2016 um 21:43 schrieb Austin Zheng :
>>> 
>>> It's not possible, even with Swift's current implementation of
>>> existentials. A protocol type P isn't considered to conform to
>>> itself, thus the following is rejected:
>>> 
>>> let a : MyProtocol = // ...
>>> func myFunc(x: T) {
>>>  // 
>>> }
>>> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type 
>>> MyProtocol"
>>> 
>>> Changing how this works is probably worth a proposal by itself.
>>> 
>>> Austin
>>> 
>>> 
>>> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution
>>> >> >
>>> wrote:
>>> 
 Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution
 >:
 
 
 on Tue Jun 07 2016, Matthew Johnson  wrote:
 
>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams
>> > >
>> wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > > >> wrote:
> 
 On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution
 >
 wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson
 >
 wrote:
>>> 
>> , but haven't realized
>> that if you step around the type relationships encoded in Self
>> requirements and associated types you end up with types that appear 
>> to
>> interoperate but in fact trap at runtime unless used in exactly the
>> right way.
> 
> Trap at runtime?  How so?  Generalized existentials should still be
> type-safe.
 
 There are two choices when you erase static type relationships:
 
 1. Acheive type-safety by trapping at runtime
 
 FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
 
 2. Don't expose protocol requirements that involve these relationships,
 which would prevent the code above from compiling and prevent
 FloatingPoint from conforming to itself.
 
> Or are you talking about the hypothetical types / behaviors people
> think they want when they don’t fully understand what is happening...
 
 I don't know what you mean here.  I think generalized existentials will
 be nice to have, but I think most people will want them to do something
 they can't possibly do.
>>> 
>>> Exactly.  What I meant is that people think they want that expression
>>> to compile because they don’t understand that the only thing it can do
>>> is trap.  I said “hypothetical” because producing a compile time error
>>> rather than a runtime trap is the only sane thing to do.  Your comment
>>> surprised me because I can’t imagine we would move forward in Swift
>>> with the approach of trapping.
>> 
>> I would very much like to be able to create instances of “Collection
>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> That will require some type mismatches to be caught at runtime via
>> trapping.
> 
> For invalid index because the existential accepts a type erased index?
 
 Exactly.
 
> How do you decide where to draw the line here?  It feels like a very
> slippery slope for a language where safety is a stated 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Jordan Rose via swift-evolution

> On Jun 8, 2016, at 13:16, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Wed Jun 08 2016, Thorsten Seitz  > wrote:
> 
>> Ah, thanks, I forgot!  I still consider this a bug, though (will have
>> to read up again what the reasons are for that behavior).
> 
> Yes, but in the case of the issue we're discussing, the choices are:
> 
> 1. Omit from the existential's API any protocol requirements that depend
>   on Self or associated types, in which case it *can't* conform to
>   itself because it doesn't fulfill the requirements.
> 
> 2. Erase type relationships and trap at runtime when they don't line up.
> 
> Matthew has been arguing against #2, but you can't “fix the bug” without
> it.

#1 has been my preference for a while as well, at least as a starting point. 
It's possible we could also "open" the existential when it's only used by one 
parameter, i.e. the first would be legal and the second wouldn't:

func foo(x: X) { … }
func test(x: Any) {
  foo(x) // okay, passes the dynamic type
}

func bar(a: X, b: X) { … }
func test(x: Any, y: Any) {
  bar(x, y) // illegal because x.dynamicType may be different from y.dynamicType
}

(The check is not as simple as "the generic parameter is only mentioned once", 
because of constraints and such. But you get the idea.)

Jordan

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Dave Abrahams via swift-evolution

on Wed Jun 08 2016, Thorsten Seitz  wrote:

> Ah, thanks, I forgot!  I still consider this a bug, though (will have
> to read up again what the reasons are for that behavior).

Yes, but in the case of the issue we're discussing, the choices are:

1. Omit from the existential's API any protocol requirements that depend
   on Self or associated types, in which case it *can't* conform to
   itself because it doesn't fulfill the requirements.

2. Erase type relationships and trap at runtime when they don't line up.

Matthew has been arguing against #2, but you can't “fix the bug” without
it.

>
> -Thorsten
>
>> Am 08.06.2016 um 21:43 schrieb Austin Zheng :
>> 
>> It's not possible, even with Swift's current implementation of
>> existentials. A protocol type P isn't considered to conform to
>> itself, thus the following is rejected:
>> 
>> let a : MyProtocol = // ...
>> func myFunc(x: T) {
>>   // 
>> }
>> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type 
>> MyProtocol"
>> 
>> Changing how this works is probably worth a proposal by itself.
>> 
>> Austin
>> 
>> 
>> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution
>> > >
>> wrote:
>> 
>> > Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution
>> > > > >:
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson  wrote:
>> >
>> >>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams
>> >>> > >>> >
>> >>> wrote:
>> >>>
>> >>>
>> >>> on Tue Jun 07 2016, Matthew Johnson > >>> > >>> >> wrote:
>> >>>
>> >>
>> > On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution
>> > > > >
>> > wrote:
>> >
>> >
>> > on Tue Jun 07 2016, Matthew Johnson
>> > > > >
>> > wrote:
>> >
>> 
>> >>> , but haven't realized
>> >>> that if you step around the type relationships encoded in Self
>> >>> requirements and associated types you end up with types that appear 
>> >>> to
>> >>> interoperate but in fact trap at runtime unless used in exactly the
>> >>> right way.
>> >>
>> >> Trap at runtime?  How so?  Generalized existentials should still be
>> >> type-safe.
>> >
>> > There are two choices when you erase static type relationships:
>> >
>> > 1. Acheive type-safety by trapping at runtime
>> >
>> > FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>> >
>> > 2. Don't expose protocol requirements that involve these relationships,
>> > which would prevent the code above from compiling and prevent
>> > FloatingPoint from conforming to itself.
>> >
>> >> Or are you talking about the hypothetical types / behaviors people
>> >> think they want when they don’t fully understand what is happening...
>> >
>> > I don't know what you mean here.  I think generalized existentials will
>> > be nice to have, but I think most people will want them to do something
>> > they can't possibly do.
>> 
>>  Exactly.  What I meant is that people think they want that expression
>>  to compile because they don’t understand that the only thing it can do
>>  is trap.  I said “hypothetical” because producing a compile time error
>>  rather than a runtime trap is the only sane thing to do.  Your comment
>>  surprised me because I can’t imagine we would move forward in Swift
>>  with the approach of trapping.
>> >>>
>> >>> I would very much like to be able to create instances of “Collection
>> >>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> >>> That will require some type mismatches to be caught at runtime via
>> >>> trapping.
>> >>
>> >> For invalid index because the existential accepts a type erased index?
>> >
>> > Exactly.
>> >
>> >> How do you decide where to draw the line here?  It feels like a very
>> >> slippery slope for a language where safety is a stated priority to
>> >> start adopting a strategy of runtime trapping for something as
>> >> fundamental as how you expose members on an existential.
>> >
>> > If you don't do this, the alternative is that “Collection where Element
>> > == Int” does not conform to Collection.  That's weird and not very
>> > useful.  You could expose all the methods that were on protocol
>> > extensions of Collection on this existential, unless they used
>> > associated types other than the element type.  But you couldn't pass the
>> > existential to a generic function like
>> >
>> >   func scrambled(_ c: C) -> [C.Element]
>> 
>> I don’t understand. Why couldn’t an existential be passed to that function?
>> 
>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Thorsten Seitz via swift-evolution
Ah, thanks, I forgot! 
I still consider this a bug, though (will have to read up again what the 
reasons are for that behavior).

-Thorsten


> Am 08.06.2016 um 21:43 schrieb Austin Zheng :
> 
> It's not possible, even with Swift's current implementation of existentials. 
> A protocol type P isn't considered to conform to itself, thus the following 
> is rejected:
> 
> let a : MyProtocol = // ...
> func myFunc(x: T) {
>   // 
> }
> myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type MyProtocol"
> 
> Changing how this works is probably worth a proposal by itself.
> 
> Austin
> 
> 
> On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution 
> > wrote:
> 
> > Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution 
> > >:
> >
> >
> > on Tue Jun 07 2016, Matthew Johnson  wrote:
> >
> >>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  >>> > wrote:
> >>>
> >>>
> >>> on Tue Jun 07 2016, Matthew Johnson  >>> >> 
> >>> wrote:
> >>>
> >>
> > On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
> > > wrote:
> >
> >
> > on Tue Jun 07 2016, Matthew Johnson  > > wrote:
> >
> 
> >>> , but haven't realized
> >>> that if you step around the type relationships encoded in Self
> >>> requirements and associated types you end up with types that appear to
> >>> interoperate but in fact trap at runtime unless used in exactly the
> >>> right way.
> >>
> >> Trap at runtime?  How so?  Generalized existentials should still be
> >> type-safe.
> >
> > There are two choices when you erase static type relationships:
> >
> > 1. Acheive type-safety by trapping at runtime
> >
> > FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
> >
> > 2. Don't expose protocol requirements that involve these relationships,
> > which would prevent the code above from compiling and prevent
> > FloatingPoint from conforming to itself.
> >
> >> Or are you talking about the hypothetical types / behaviors people
> >> think they want when they don’t fully understand what is happening...
> >
> > I don't know what you mean here.  I think generalized existentials will
> > be nice to have, but I think most people will want them to do something
> > they can't possibly do.
> 
>  Exactly.  What I meant is that people think they want that expression
>  to compile because they don’t understand that the only thing it can do
>  is trap.  I said “hypothetical” because producing a compile time error
>  rather than a runtime trap is the only sane thing to do.  Your comment
>  surprised me because I can’t imagine we would move forward in Swift
>  with the approach of trapping.
> >>>
> >>> I would very much like to be able to create instances of “Collection
> >>> where Element == Int” so we can throw away the wrappers in the stdlib.
> >>> That will require some type mismatches to be caught at runtime via
> >>> trapping.
> >>
> >> For invalid index because the existential accepts a type erased index?
> >
> > Exactly.
> >
> >> How do you decide where to draw the line here?  It feels like a very
> >> slippery slope for a language where safety is a stated priority to
> >> start adopting a strategy of runtime trapping for something as
> >> fundamental as how you expose members on an existential.
> >
> > If you don't do this, the alternative is that “Collection where Element
> > == Int” does not conform to Collection.  That's weird and not very
> > useful.  You could expose all the methods that were on protocol
> > extensions of Collection on this existential, unless they used
> > associated types other than the element type.  But you couldn't pass the
> > existential to a generic function like
> >
> >   func scrambled(_ c: C) -> [C.Element]
> 
> I don’t understand. Why couldn’t an existential be passed to that function?
> 
> -Thorsten
> 
> 
> 
> >
> >> IMO you should *have* to introduce unsafe behavior like that manually.
> >
> >  Collection where Element == Int & Index == *
> >
> > ?
> >
> >> Collection indices are already something that isn’t fully statically
> >> safe so I understand why you might want to allow this.
> >
> > By the same measure, so are Ints :-)
> >
> > The fact that a type's methods have preconditions does *not* make it
> > “statically unsafe.”
> >
> >> But I don’t think having the language's existentials do this
> >> automatically is the right approach.  Maybe there is another approach
> >> that could be used in targeted use cases where the less safe behavior
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Austin Zheng via swift-evolution
It's not possible, even with Swift's current implementation of
existentials. A protocol type P isn't considered to conform to itself, thus
the following is rejected:

let a : MyProtocol = // ...
func myFunc(x: T) {
  // 
}
myFunc(a) // "Cannot invoke 'myFunc' with an argument list of type
MyProtocol"

Changing how this works is probably worth a proposal by itself.

Austin


On Wed, Jun 8, 2016 at 12:34 PM, Thorsten Seitz via swift-evolution <
swift-evolution@swift.org> wrote:

>
> > Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution <
> swift-evolution@swift.org>:
> >
> >
> > on Tue Jun 07 2016, Matthew Johnson  wrote:
> >
> >>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
> >>>
> >>>
> >>> on Tue Jun 07 2016, Matthew Johnson  http://matthew-at-anandabits.com/>> wrote:
> >>>
> >>
> > On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> >
> > on Tue Jun 07 2016, Matthew Johnson 
> wrote:
> >
> 
> >>> , but haven't realized
> >>> that if you step around the type relationships encoded in Self
> >>> requirements and associated types you end up with types that
> appear to
> >>> interoperate but in fact trap at runtime unless used in exactly the
> >>> right way.
> >>
> >> Trap at runtime?  How so?  Generalized existentials should still be
> >> type-safe.
> >
> > There are two choices when you erase static type relationships:
> >
> > 1. Acheive type-safety by trapping at runtime
> >
> > FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
> >
> > 2. Don't expose protocol requirements that involve these
> relationships,
> > which would prevent the code above from compiling and prevent
> > FloatingPoint from conforming to itself.
> >
> >> Or are you talking about the hypothetical types / behaviors people
> >> think they want when they don’t fully understand what is
> happening...
> >
> > I don't know what you mean here.  I think generalized existentials
> will
> > be nice to have, but I think most people will want them to do
> something
> > they can't possibly do.
> 
>  Exactly.  What I meant is that people think they want that expression
>  to compile because they don’t understand that the only thing it can do
>  is trap.  I said “hypothetical” because producing a compile time error
>  rather than a runtime trap is the only sane thing to do.  Your comment
>  surprised me because I can’t imagine we would move forward in Swift
>  with the approach of trapping.
> >>>
> >>> I would very much like to be able to create instances of “Collection
> >>> where Element == Int” so we can throw away the wrappers in the stdlib.
> >>> That will require some type mismatches to be caught at runtime via
> >>> trapping.
> >>
> >> For invalid index because the existential accepts a type erased index?
> >
> > Exactly.
> >
> >> How do you decide where to draw the line here?  It feels like a very
> >> slippery slope for a language where safety is a stated priority to
> >> start adopting a strategy of runtime trapping for something as
> >> fundamental as how you expose members on an existential.
> >
> > If you don't do this, the alternative is that “Collection where Element
> > == Int” does not conform to Collection.  That's weird and not very
> > useful.  You could expose all the methods that were on protocol
> > extensions of Collection on this existential, unless they used
> > associated types other than the element type.  But you couldn't pass the
> > existential to a generic function like
> >
> >   func scrambled(_ c: C) -> [C.Element]
>
> I don’t understand. Why couldn’t an existential be passed to that function?
>
> -Thorsten
>
>
>
> >
> >> IMO you should *have* to introduce unsafe behavior like that manually.
> >
> >  Collection where Element == Int & Index == *
> >
> > ?
> >
> >> Collection indices are already something that isn’t fully statically
> >> safe so I understand why you might want to allow this.
> >
> > By the same measure, so are Ints :-)
> >
> > The fact that a type's methods have preconditions does *not* make it
> > “statically unsafe.”
> >
> >> But I don’t think having the language's existentials do this
> >> automatically is the right approach.  Maybe there is another approach
> >> that could be used in targeted use cases where the less safe behavior
> >> makes sense and is carefully designed.
> >
> > Whether it makes sense or not really depends on the use-cases.  There's
> > little point in generalizing existentials if the result isn't very
> useful.
> > The way to find out is to take a look at the examples we currently have
> > of protocols with associated types or Self requirements and consider
> > what you'd be able to do with their existentials if type relationships
> > couldn't be erased.
> >
> > We have known use-cases, 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Thorsten Seitz via swift-evolution

> Am 08.06.2016 um 20:33 schrieb Dave Abrahams via swift-evolution 
> :
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
>>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson >> > wrote:
>>> 
>> 
> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
 
>>> , but haven't realized
>>> that if you step around the type relationships encoded in Self
>>> requirements and associated types you end up with types that appear to
>>> interoperate but in fact trap at runtime unless used in exactly the
>>> right way.
>> 
>> Trap at runtime?  How so?  Generalized existentials should still be
>> type-safe.  
> 
> There are two choices when you erase static type relationships:
> 
> 1. Acheive type-safety by trapping at runtime
> 
> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
> 
> 2. Don't expose protocol requirements that involve these relationships,
> which would prevent the code above from compiling and prevent
> FloatingPoint from conforming to itself.
> 
>> Or are you talking about the hypothetical types / behaviors people
>> think they want when they don’t fully understand what is happening...
> 
> I don't know what you mean here.  I think generalized existentials will
> be nice to have, but I think most people will want them to do something
> they can't possibly do.
 
 Exactly.  What I meant is that people think they want that expression
 to compile because they don’t understand that the only thing it can do
 is trap.  I said “hypothetical” because producing a compile time error
 rather than a runtime trap is the only sane thing to do.  Your comment
 surprised me because I can’t imagine we would move forward in Swift
 with the approach of trapping.
>>> 
>>> I would very much like to be able to create instances of “Collection
>>> where Element == Int” so we can throw away the wrappers in the stdlib.
>>> That will require some type mismatches to be caught at runtime via
>>> trapping.
>> 
>> For invalid index because the existential accepts a type erased index?
> 
> Exactly.
> 
>> How do you decide where to draw the line here?  It feels like a very
>> slippery slope for a language where safety is a stated priority to
>> start adopting a strategy of runtime trapping for something as
>> fundamental as how you expose members on an existential.
> 
> If you don't do this, the alternative is that “Collection where Element
> == Int” does not conform to Collection.  That's weird and not very
> useful.  You could expose all the methods that were on protocol
> extensions of Collection on this existential, unless they used
> associated types other than the element type.  But you couldn't pass the
> existential to a generic function like
> 
>   func scrambled(_ c: C) -> [C.Element]

I don’t understand. Why couldn’t an existential be passed to that function?

-Thorsten



> 
>> IMO you should *have* to introduce unsafe behavior like that manually.
> 
>  Collection where Element == Int & Index == *
> 
> ?
> 
>> Collection indices are already something that isn’t fully statically
>> safe so I understand why you might want to allow this.  
> 
> By the same measure, so are Ints :-)
> 
> The fact that a type's methods have preconditions does *not* make it
> “statically unsafe.”
> 
>> But I don’t think having the language's existentials do this
>> automatically is the right approach.  Maybe there is another approach
>> that could be used in targeted use cases where the less safe behavior
>> makes sense and is carefully designed.
> 
> Whether it makes sense or not really depends on the use-cases.  There's
> little point in generalizing existentials if the result isn't very useful.
> The way to find out is to take a look at the examples we currently have
> of protocols with associated types or Self requirements and consider
> what you'd be able to do with their existentials if type relationships
> couldn't be erased.  
> 
> We have known use-cases, currently emulated in the standard library, for
> existentials with erased type relationships.  *If* these represent the
> predominant use cases for something like generalized existentials, it
> seems to me that the language feature should support that.  Note: I have
> not seen anyone build an emulation of the other kind of generalized
> existential.  My theory: there's a good reason for that :-).
> 
> -- 
> Dave
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Dave Abrahams via swift-evolution

on Tue Jun 07 2016, Matthew Johnson  wrote:

>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > > wrote:
>> 
>
 On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
  wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson  wrote:
 
>>> 
>> , but haven't realized
>> that if you step around the type relationships encoded in Self
>> requirements and associated types you end up with types that appear to
>> interoperate but in fact trap at runtime unless used in exactly the
>> right way.
> 
> Trap at runtime?  How so?  Generalized existentials should still be
> type-safe.  
 
 There are two choices when you erase static type relationships:
 
 1. Acheive type-safety by trapping at runtime
 
 FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
 
 2. Don't expose protocol requirements that involve these relationships,
  which would prevent the code above from compiling and prevent
  FloatingPoint from conforming to itself.
 
> Or are you talking about the hypothetical types / behaviors people
> think they want when they don’t fully understand what is happening...
 
 I don't know what you mean here.  I think generalized existentials will
 be nice to have, but I think most people will want them to do something
 they can't possibly do.
>>> 
>>> Exactly.  What I meant is that people think they want that expression
>>> to compile because they don’t understand that the only thing it can do
>>> is trap.  I said “hypothetical” because producing a compile time error
>>> rather than a runtime trap is the only sane thing to do.  Your comment
>>> surprised me because I can’t imagine we would move forward in Swift
>>> with the approach of trapping.
>> 
>> I would very much like to be able to create instances of “Collection
>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> That will require some type mismatches to be caught at runtime via
>> trapping.
>
> For invalid index because the existential accepts a type erased index?

Exactly.

> How do you decide where to draw the line here?  It feels like a very
> slippery slope for a language where safety is a stated priority to
> start adopting a strategy of runtime trapping for something as
> fundamental as how you expose members on an existential.

If you don't do this, the alternative is that “Collection where Element
== Int” does not conform to Collection.  That's weird and not very
useful.  You could expose all the methods that were on protocol
extensions of Collection on this existential, unless they used
associated types other than the element type.  But you couldn't pass the
existential to a generic function like

   func scrambled(_ c: C) -> [C.Element]

> IMO you should *have* to introduce unsafe behavior like that manually.

  Collection where Element == Int & Index == *

?

> Collection indices are already something that isn’t fully statically
> safe so I understand why you might want to allow this.  

By the same measure, so are Ints :-)

The fact that a type's methods have preconditions does *not* make it
“statically unsafe.”

> But I don’t think having the language's existentials do this
> automatically is the right approach.  Maybe there is another approach
> that could be used in targeted use cases where the less safe behavior
> makes sense and is carefully designed.

Whether it makes sense or not really depends on the use-cases.  There's
little point in generalizing existentials if the result isn't very useful.
The way to find out is to take a look at the examples we currently have
of protocols with associated types or Self requirements and consider
what you'd be able to do with their existentials if type relationships
couldn't be erased.  

We have known use-cases, currently emulated in the standard library, for
existentials with erased type relationships.  *If* these represent the
predominant use cases for something like generalized existentials, it
seems to me that the language feature should support that.  Note: I have
not seen anyone build an emulation of the other kind of generalized
existential.  My theory: there's a good reason for that :-).

-- 
Dave
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-08 Thread Matthew Johnson via swift-evolution

> On Jun 7, 2016, at 9:27 PM, Matthew Johnson  wrote:
> 
>> 
>> On Jun 7, 2016, at 9:15 PM, Dave Abrahams > > wrote:
>> 
>> 
>> on Tue Jun 07 2016, Matthew Johnson > > wrote:
>> 
 On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
 > wrote:
 
 
 on Tue Jun 07 2016, Matthew Johnson > wrote:
 
>>> 
>> , but haven't realized
>> that if you step around the type relationships encoded in Self
>> requirements and associated types you end up with types that appear to
>> interoperate but in fact trap at runtime unless used in exactly the
>> right way.
> 
> Trap at runtime?  How so?  Generalized existentials should still be
> type-safe.  
 
 There are two choices when you erase static type relationships:
 
 1. Acheive type-safety by trapping at runtime
 
 FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
 
 2. Don't expose protocol requirements that involve these relationships,
  which would prevent the code above from compiling and prevent
  FloatingPoint from conforming to itself.
 
> Or are you talking about the hypothetical types / behaviors people
> think they want when they don’t fully understand what is happening...
 
 I don't know what you mean here.  I think generalized existentials will
 be nice to have, but I think most people will want them to do something
 they can't possibly do.
>>> 
>>> Exactly.  What I meant is that people think they want that expression
>>> to compile because they don’t understand that the only thing it can do
>>> is trap.  I said “hypothetical” because producing a compile time error
>>> rather than a runtime trap is the only sane thing to do.  Your comment
>>> surprised me because I can’t imagine we would move forward in Swift
>>> with the approach of trapping.
>> 
>> I would very much like to be able to create instances of “Collection
>> where Element == Int” so we can throw away the wrappers in the stdlib.
>> That will require some type mismatches to be caught at runtime via
>> trapping.

BTW, Austin’s generalized existentials proposal has several examples of how 
existential collections would work: 
https://github.com/austinzheng/swift-evolution/blob/az-existentials/proposals/-enhanced-existentials.md#protocol-apis-and-associated-types
 
.
  

In what ways do you find this functionality insufficient?  What operations do 
you want to be able to do that this doesn’t support (and can only be supported 
in an unsafe way that must trap for invalid input)?

> 
> For invalid index because the existential accepts a type erased index?
> 
> How do you decide where to draw the line here?  It feels like a very slippery 
> slope for a language where safety is a stated priority to start adopting a 
> strategy of runtime trapping for something as fundamental as how you expose 
> members on an existential.  
> 
> IMO you should *have* to introduce unsafe behavior like that manually.  
> Collection indices are already something that isn’t fully statically safe so 
> I understand why you might want to allow this.  But I don’t think having the 
> language's existentials do this automatically is the right approach.  Maybe 
> there is another approach that could be used in targeted use cases where the 
> less safe behavior makes sense and is carefully designed.
> 
>> 
>>> 
>>> The low hanging fruit in the “protocols whose existentials conform to
>>> the protocol” space is simple protocols that can already by
>>> existentials today (like CustomStringConvertible).  I don’t know
>>> enough about Swift’s implementation to comment on how complex it is
>>> there, but there aren’t any theoretical problems with making their
>>> existentials conform.
>>> 
 
 -- 
 -Dave
 
 ___
 swift-evolution mailing list
 swift-evolution@swift.org 
 https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> -- 
>> Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-07 Thread Matthew Johnson via swift-evolution

> On Jun 7, 2016, at 9:15 PM, Dave Abrahams  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  > wrote:
> 
>>> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> on Tue Jun 07 2016, Matthew Johnson  wrote:
>>> 
>> 
> , but haven't realized
> that if you step around the type relationships encoded in Self
> requirements and associated types you end up with types that appear to
> interoperate but in fact trap at runtime unless used in exactly the
> right way.
 
 Trap at runtime?  How so?  Generalized existentials should still be
 type-safe.  
>>> 
>>> There are two choices when you erase static type relationships:
>>> 
>>> 1. Acheive type-safety by trapping at runtime
>>> 
>>> FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
>>> 
>>> 2. Don't expose protocol requirements that involve these relationships,
>>>  which would prevent the code above from compiling and prevent
>>>  FloatingPoint from conforming to itself.
>>> 
 Or are you talking about the hypothetical types / behaviors people
 think they want when they don’t fully understand what is happening...
>>> 
>>> I don't know what you mean here.  I think generalized existentials will
>>> be nice to have, but I think most people will want them to do something
>>> they can't possibly do.
>> 
>> Exactly.  What I meant is that people think they want that expression
>> to compile because they don’t understand that the only thing it can do
>> is trap.  I said “hypothetical” because producing a compile time error
>> rather than a runtime trap is the only sane thing to do.  Your comment
>> surprised me because I can’t imagine we would move forward in Swift
>> with the approach of trapping.
> 
> I would very much like to be able to create instances of “Collection
> where Element == Int” so we can throw away the wrappers in the stdlib.
> That will require some type mismatches to be caught at runtime via
> trapping.

For invalid index because the existential accepts a type erased index?

How do you decide where to draw the line here?  It feels like a very slippery 
slope for a language where safety is a stated priority to start adopting a 
strategy of runtime trapping for something as fundamental as how you expose 
members on an existential.  

IMO you should *have* to introduce unsafe behavior like that manually.  
Collection indices are already something that isn’t fully statically safe so I 
understand why you might want to allow this.  But I don’t think having the 
language's existentials do this automatically is the right approach.  Maybe 
there is another approach that could be used in targeted use cases where the 
less safe behavior makes sense and is carefully designed.

> 
>> 
>> The low hanging fruit in the “protocols whose existentials conform to
>> the protocol” space is simple protocols that can already by
>> existentials today (like CustomStringConvertible).  I don’t know
>> enough about Swift’s implementation to comment on how complex it is
>> there, but there aren’t any theoretical problems with making their
>> existentials conform.
>> 
>>> 
>>> -- 
>>> -Dave
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> -- 
> Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-07 Thread Matthew Johnson via swift-evolution

> On Jun 7, 2016, at 4:13 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
>>> , but haven't realized
>>> that if you step around the type relationships encoded in Self
>>> requirements and associated types you end up with types that appear to
>>> interoperate but in fact trap at runtime unless used in exactly the
>>> right way.
>> 
>> Trap at runtime?  How so?  Generalized existentials should still be
>> type-safe.  
> 
> There are two choices when you erase static type relationships:
> 
> 1. Acheive type-safety by trapping at runtime
> 
>  FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap
> 
> 2. Don't expose protocol requirements that involve these relationships,
>   which would prevent the code above from compiling and prevent
>   FloatingPoint from conforming to itself.
> 
>> Or are you talking about the hypothetical types / behaviors people
>> think they want when they don’t fully understand what is happening...
> 
> I don't know what you mean here.  I think generalized existentials will
> be nice to have, but I think most people will want them to do something
> they can't possibly do.

Exactly.  What I meant is that people think they want that expression to 
compile because they don’t understand that the only thing it can do is trap.  I 
said “hypothetical” because producing a compile time error rather than a 
runtime trap is the only sane thing to do.  Your comment surprised me because I 
can’t imagine we would move forward in Swift with the approach of trapping.

The low hanging fruit in the “protocols whose existentials conform to the 
protocol” space is simple protocols that can already by existentials today 
(like CustomStringConvertible).  I don’t know enough about Swift’s 
implementation to comment on how complex it is there, but there aren’t any 
theoretical problems with making their existentials conform. 

> 
> -- 
> -Dave
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-07 Thread Dave Abrahams via swift-evolution

on Tue Jun 07 2016, Matthew Johnson  wrote:

>> , but haven't realized
>> that if you step around the type relationships encoded in Self
>> requirements and associated types you end up with types that appear to
>> interoperate but in fact trap at runtime unless used in exactly the
>> right way.
>
> Trap at runtime?  How so?  Generalized existentials should still be
> type-safe.  

There are two choices when you erase static type relationships:

1. Acheive type-safety by trapping at runtime

  FloatingPoint(3.0 as Float) + FloatingPoint(3.0 as Double) // trap

2. Don't expose protocol requirements that involve these relationships,
   which would prevent the code above from compiling and prevent
   FloatingPoint from conforming to itself.

> Or are you talking about the hypothetical types / behaviors people
> think they want when they don’t fully understand what is happening...

I don't know what you mean here.  I think generalized existentials will
be nice to have, but I think most people will want them to do something
they can't possibly do.

-- 
-Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-07 Thread L Mihalkovic via swift-evolution

> On Jun 7, 2016, at 7:51 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
>>> On Jun 6, 2016, at 12:22 AM, Dave Abrahams 
>> wrote:
>>> 
>>> 
>>> on Sun Jun 05 2016, Matthew Johnson > > wrote:
>>> 
>> 
 Sent from my iPhone
 
> On Jun 5, 2016, at 3:51 PM, Dave Abrahams via swift-evolution
>  wrote:
> 
> 
>> on Wed May 25 2016, Matthew Johnson  wrote:
>> 
>> Sent from my iPad
>> 
>>> On May 25, 2016, at 12:10 PM, Jordan Rose via swift-evolution
>>>  wrote:
>>> 
>>> 
> On May 25, 2016, at 05:27, Brent Royal-Gordon via swift-evolution
>  wrote:
> 
> AFAIK an existential type is a type T with type parameters that
> are still abstract (see for example
> https://en.wikipedia.org/wiki/Type_system#Existential_types),
> i.e. have not been assigned concrete values.
 
 My understanding is that, in Swift, the instance used to store
 something whose concrete type is unknown (i.e. is still abstract),
 but which is known to conform to some protocol, is called an
 "existential". Protocols with associated values cannot be packed
 into normal existentials because, even though we know that the
 concrete type conforms to some protocol, the associated types
 represent additional unknowns, and Swift cannot be sure how to
 translate uses of those unknown types into callable members. Hence,
 protocols with associated types are sometimes called
 "non-existential".
 
 If I am misusing the terminology in this area, please understand
 that that's what I mean when I use that word.
>>> 
>>> We’re not consistent about it, but an “existential value” is a value
>>> with protocol or protocol composition type. My mnemonic for this is
>>> that all we know is that certain operations exist (unlike a generic
>>> value, where we also have access to the type). John could explain it
>>> more formally. We sometimes use “existentials” as a (noun) shorthand
>>> for “existential value”.
>>> 
>>> In the compiler source, all protocols and protocol compositions are
>>> referred to as “existential types”, whether they have associated
>>> types or not. Again, a protocol asserts the existence (and
>>> semantics) of various operations, but nothing else about the
>>> conforming type. (Except perhaps that it’s a class.) All protocols
>>> are thus “existential types” whether or not the language supports
>>> values having that type.
>>> 
>>> It is incorrect to say that protocols with associated types (or
>>> requirements involving Self) are “non-existential”.
>> 
>> I haven't heard people using this term myself, but I imagine they
>> probably mean "can't form an existential value with the protocol".
>> There certainly appears to be a lot of confusion in the community with
>> many not realizing that this is a temporary limitation of the
>> implementation, not a necessary fact.
> 
> As far as I know there is no known way to make protocols with Self
> requirements usefully “existentiable,” or whatever you want to
>> call it.
> So unless I'm missing something, in this respect, the limitation
>> is not
> temporary at all.
 
 Take a look at the Equatable example in the opening existentials
 section of Doug's manifesto:
 
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160229/011666.html
>>> 
>>> Yes, note that I said *usefully* “existential.”
>> 
>> Fair enough.  But note that I was only talking about the inability to
>> form and open such an existential which appears likely to be a
>> temporary limitation given the generics manifesto (of course things
>> could change).
>> 
>>> While we can of course downcast in this way, you have to handle the
>>> failure case and it's not like you can use this to make a
>>> heterogeneous Set.  AFAICT, this is not at all like what
>>> happens with associated types, where Collection has
>>> obvious uses.
>> 
>> We can’t use this to form Set because existentials don’t
>> conform to the protocol.  I know there is complexity in implementing
>> this and it is not possible to synthesize conformance of the
>> existential for all protocols, but AFAIK it isn’t a settled point that
>> we won’t try to improve the situation in some way.  
> 
> Of course.  I'm just trying to point out that such existentials are
> likely to be a whole lot less useful than many people might think.
> 
>> Maybe we can make progress here somehow.
> 
> Maybe.  It's a research project.
> 
>> In the meantime, we can make a simple wrapper type to provide the
>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-06-07 Thread Matthew Johnson via swift-evolution

> On Jun 7, 2016, at 12:51 PM, Dave Abrahams  wrote:
> 
> 
> on Tue Jun 07 2016, Matthew Johnson  wrote:
> 
>>> On Jun 6, 2016, at 12:22 AM, Dave Abrahams 
>> wrote:
>>> 
>>> 
>>> on Sun Jun 05 2016, Matthew Johnson > > wrote:
>>> 
>> 
 Sent from my iPhone
 
> On Jun 5, 2016, at 3:51 PM, Dave Abrahams via swift-evolution
>  wrote:
> 
> 
>> on Wed May 25 2016, Matthew Johnson  wrote:
>> 
>> Sent from my iPad
>> 
>>> On May 25, 2016, at 12:10 PM, Jordan Rose via swift-evolution
>>>  wrote:
>>> 
>>> 
> On May 25, 2016, at 05:27, Brent Royal-Gordon via swift-evolution
>  wrote:
> 
> AFAIK an existential type is a type T with type parameters that
> are still abstract (see for example
> https://en.wikipedia.org/wiki/Type_system#Existential_types),
> i.e. have not been assigned concrete values.
 
 My understanding is that, in Swift, the instance used to store
 something whose concrete type is unknown (i.e. is still abstract),
 but which is known to conform to some protocol, is called an
 "existential". Protocols with associated values cannot be packed
 into normal existentials because, even though we know that the
 concrete type conforms to some protocol, the associated types
 represent additional unknowns, and Swift cannot be sure how to
 translate uses of those unknown types into callable members. Hence,
 protocols with associated types are sometimes called
 "non-existential".
 
 If I am misusing the terminology in this area, please understand
 that that's what I mean when I use that word.
>>> 
>>> We’re not consistent about it, but an “existential value” is a value
>>> with protocol or protocol composition type. My mnemonic for this is
>>> that all we know is that certain operations exist (unlike a generic
>>> value, where we also have access to the type). John could explain it
>>> more formally. We sometimes use “existentials” as a (noun) shorthand
>>> for “existential value”.
>>> 
>>> In the compiler source, all protocols and protocol compositions are
>>> referred to as “existential types”, whether they have associated
>>> types or not. Again, a protocol asserts the existence (and
>>> semantics) of various operations, but nothing else about the
>>> conforming type. (Except perhaps that it’s a class.) All protocols
>>> are thus “existential types” whether or not the language supports
>>> values having that type.
>>> 
>>> It is incorrect to say that protocols with associated types (or
>>> requirements involving Self) are “non-existential”.
>> 
>> I haven't heard people using this term myself, but I imagine they
>> probably mean "can't form an existential value with the protocol".
>> There certainly appears to be a lot of confusion in the community with
>> many not realizing that this is a temporary limitation of the
>> implementation, not a necessary fact.
> 
> As far as I know there is no known way to make protocols with Self
> requirements usefully “existentiable,” or whatever you want to
>> call it.
> So unless I'm missing something, in this respect, the limitation
>> is not
> temporary at all.
 
 Take a look at the Equatable example in the opening existentials
 section of Doug's manifesto:
 
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160229/011666.html
>>> 
>>> Yes, note that I said *usefully* “existential.”
>> 
>> Fair enough.  But note that I was only talking about the inability to
>> form and open such an existential which appears likely to be a
>> temporary limitation given the generics manifesto (of course things
>> could change).
>> 
>>> While we can of course downcast in this way, you have to handle the
>>> failure case and it's not like you can use this to make a
>>> heterogeneous Set.  AFAICT, this is not at all like what
>>> happens with associated types, where Collection has
>>> obvious uses.
>> 
>> We can’t use this to form Set because existentials don’t
>> conform to the protocol.  I know there is complexity in implementing
>> this and it is not possible to synthesize conformance of the
>> existential for all protocols, but AFAIK it isn’t a settled point that
>> we won’t try to improve the situation in some way.  
> 
> Of course.  I'm just trying to point out that such existentials are
> likely to be a whole lot less useful than many people might think.
> 
>> Maybe we can make progress here somehow.
> 
> Maybe.  It's a research project.
> 
>> In the meantime, we can make a simple wrapper type to provide the
>> required conformance and 

  1   2   >