Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-25 Thread Joshua Alvarado via swift-evolution
Okay I will resubmit after post Swift 4.0 scope is discussed. Thanks! 

Alvarado, Joshua

> On Apr 25, 2017, at 11:08 AM, Douglas Gregor  wrote:
> 
> 
>> On Apr 24, 2017, at 12:57 PM, Joshua Alvarado  
>> wrote:
>> 
>> When would be a good time to resubmit this proposal for discussion?
> 
> Sometime in the summer we’re going to start talking about the scope of Swift 
> post-4.0.
> 
>> Or can I still proceed with the review and it possibly gets deferred but at 
>> least be put in the pipeline (if deferred)?
> 
> We try not to let the review process get *too* far ahead of the actual 
> implementation, because detailed design review for acceptance is itself a 
> time-consuming process. 
> 
>   - Doug
> 
>> 
>>> On Mon, Apr 24, 2017 at 9:07 AM, Douglas Gregor  wrote:
>>> 
 On Apr 24, 2017, at 7:23 AM, T.J. Usiyan via swift-evolution 
  wrote:
 
 /me Pushes implementation detail related concerns out of head
 
 +1
 
 
 I want this feature but I seriously doubt that it is feasible at the 
 moment. There are so many 'more pressing' features that, even if this were 
 accepted now, it wouldn't be implemented it in time for Swift 4.
>>> 
>>> Out of scope for Swift 4, certainly. It may not look like it, but this is a 
>>> fairly large feature. I suggest reading up on generalized algebraic data 
>>> types (GADTs), which is the more programming-language-theoretical name for 
>>> what you’re describing here.
>>> 
>>> - Doug
>>> 
 
 That said, I would love to be incorrect. 
 
> On Mon, Apr 24, 2017 at 9:57 AM, Joshua Alvarado via swift-evolution 
>  wrote:
> Here is my pitch on adding generics to enum cases and not to the enum 
> type itself. Let me know if you have an improvements or modifications 
> lets open it to discussion thank you swiftys! :)
> Enum with generic cases
> Proposal: SE-
> Authors: Joshua Alvarado
> Review Manager: TBD
> Status: PITCH
> During the review process, add the following fields as needed:
> 
> Decision Notes: Rationale, Additional Commentary
> Bugs: SR-, SR-
> Previous Revision: 1
> Previous Proposal: SE-
> Introduction
> 
> This proposal adds a change to the enumeration type that allows an enum 
> case to cast a generic on its associated value.
> 
> Swift-evolution thread: Discussion thread topic for that proposal
> 
> Motivation
> 
> Enums currently support generics, but they are added onto the type 
> itself. This can cause adverse syntax when implementing generics for 
> associated values to be stored along each case. The enum case holds the 
> associated value (not the enum type itself) so should create its own 
> value constraints.
> 
> Proposed solution
> 
> The generic is to be casted on the case of the enum and not on the enum 
> itself.
> 
> Detailed design
> 
> Current implementation:
> 
> // enum with two generic types
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> 
> // U is to be casted but it is not even used
> let foo: Foo = .bar(obj: "hash")
> 
> // Creating an optional enum, the generics have to be casted without a 
> value set
> // The casting is really not needed as the values should be casted not 
> the enum
> var foo1: Foo?
> 
> // Collections don’t look great either
> var foos = [Foo]()
> foos.append(.bar(obj:"hash"))
> Proposed solution
> 
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> 
> // generic type inferred on T
> var foo: Foo = .bar(obj: "hash") 
> 
> // doesn’t need to cast the generic on the optional enum
> // the associated value will hold the cast
> var foo1: Foo? 
> 
> // This also gives better syntax with collections of enums with 
> associated types
> var foos = [Foo]()
> foos.append(.bar(obj: "hey")
> Source compatibility
> 
> This may cause subtle breaking changes for areas in code with generic 
> enum cases. The compiler could help with the change by finding the 
> associated generic and updating the case with the new syntax.
> 
> Alternatives considered
> 
> An alternative would be to extend the associatedtype keyword to the enum 
> type.
> 
> enum Foo {
> associatedtype T = Hashable
> case bar(obj: T)
> }
> 
> Copy of proposal can be found here Swift proposal on github
> 
> -- 
> Joshua Alvarado
> alvaradojosh...@gmail.com
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-25 Thread Douglas Gregor via swift-evolution

> On Apr 24, 2017, at 12:57 PM, Joshua Alvarado  
> wrote:
> 
> When would be a good time to resubmit this proposal for discussion?

Sometime in the summer we’re going to start talking about the scope of Swift 
post-4.0.

> Or can I still proceed with the review and it possibly gets deferred but at 
> least be put in the pipeline (if deferred)?

We try not to let the review process get *too* far ahead of the actual 
implementation, because detailed design review for acceptance is itself a 
time-consuming process. 

- Doug

> 
> On Mon, Apr 24, 2017 at 9:07 AM, Douglas Gregor  > wrote:
> 
>> On Apr 24, 2017, at 7:23 AM, T.J. Usiyan via swift-evolution 
>> > wrote:
>> 
>> /me Pushes implementation detail related concerns out of head
>> 
>> +1
>> 
>> 
>> I want this feature but I seriously doubt that it is feasible at the moment. 
>> There are so many 'more pressing' features that, even if this were accepted 
>> now, it wouldn't be implemented it in time for Swift 4.
> 
> Out of scope for Swift 4, certainly. It may not look like it, but this is a 
> fairly large feature. I suggest reading up on generalized algebraic data 
> types  
> (GADTs), which is the more programming-language-theoretical name for what 
> you’re describing here.
> 
>   - Doug
> 
>> 
>> That said, I would love to be incorrect. 
>> 
>> On Mon, Apr 24, 2017 at 9:57 AM, Joshua Alvarado via swift-evolution 
>> > wrote:
>> Here is my pitch on adding generics to enum cases and not to the enum type 
>> itself. Let me know if you have an improvements or modifications lets open 
>> it to discussion thank you swiftys! :)
>> 
>> Enum with generic cases
>> 
>> Proposal: SE- 
>> 
>> Authors: Joshua Alvarado 
>> Review Manager: TBD
>> Status: PITCH
>> During the review process, add the following fields as needed:
>> 
>> Decision Notes: Rationale 
>> , Additional Commentary 
>> 
>> Bugs: SR- , SR- 
>> 
>> Previous Revision: 1 
>> 
>> Previous Proposal: SE- 
>> 
>>  
>> Introduction
>> 
>> This proposal adds a change to the enumeration type that allows an enum case 
>> to cast a generic on its associated value.
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal 
>> 
>>  
>> Motivation
>> 
>> Enums currently support generics, but they are added onto the type itself. 
>> This can cause adverse syntax when implementing generics for associated 
>> values to be stored along each case. The enum case holds the associated 
>> value (not the enum type itself) so should create its own value constraints.
>> 
>>  
>> Proposed
>>  solution
>> 
>> The generic is to be casted on the case of the enum and not on the enum 
>> itself.
>> 
>>  
>> Detailed
>>  design
>> 
>> Current implementation:
>> 
>> // enum with two generic types
>> enum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> }
>> 
>> // U is to be casted but it is not even used
>> let foo: Foo = .bar(obj: "hash")
>> 
>> // Creating an optional enum, the generics have to be casted without a value 
>> set
>> // The casting is really not needed as the values should be casted not the 
>> enum
>> var foo1: Foo?
>> 
>> // Collections don’t look great either
>> var foos = [Foo]()
>> foos.append(.bar(obj:"hash"))
>> Proposed solution
>> 
>> enum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> }
>> 
>> // generic type inferred on T
>> var foo: Foo = .bar(obj: "hash") 
>> 
>> // doesn’t need to cast the generic on the optional enum
>> // the associated value will hold the cast
>> var foo1: Foo? 
>> 
>> // This also gives better syntax with collections of enums with associated 
>> types
>> var foos = [Foo]()
>> foos.append(.bar(obj: "hey")
>>  
>> Source
>>  compatibility
>> 
>> This may cause subtle breaking changes for areas in 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Austin Zheng via swift-evolution
I once put together a sketch for a proposal for GADTs. I wouldn't recommend
it be submitted for review today (or ever, really), but it's there if
anyone is interested.

https://github.com/austinzheng/swift-evolution/blob/az-gadt/proposals/-enums-as-gadts.md

Best,
Austin

On Mon, Apr 24, 2017 at 3:24 PM, Jaden Geller via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Apr 24, 2017, at 3:21 PM, Kevin Nattinger  wrote:
>
>
> On Apr 24, 2017, at 3:16 PM, Jaden Geller  wrote:
>
>
> On Apr 24, 2017, at 2:38 PM, Kevin Nattinger  wrote:
>
>
> How can I improve your understanding?
>
>
> Given the enum I was using earlier:
>
> enum Thing {
> case thingOne(T)
> case thingTwo(T)
> }
>
> - Write a function that takes a thingOne or thingTwo but
> nothing else.
>
>
> This isn’t possible since generic types introduced on cases are erased in
> the type of `Thing`.
>
> We can actually already achieve what you want by moving the generics onto
> the type itself, and this is already possible in Swift! No new features are
> necessary.
>
> ```
> enum Thing {
> case thingOne(T1)
> case thingTwo(T2)
> }
>
> func test(_ x: Thing) {
> switch x {
> case .thingOne(let s):
> print("The string has value \(s)!")
> case .thingTwo(let i):
> print("The int has value \(i)!")
> }
> }
> ```
>
>
> Yes, that was almost exactly my original example. My understanding of the
> proposal is that it will remove that capability, which I find completely
> unacceptable.
>
>
> Hi Kevin,
>
> If that is what is being proposed, I agree that that is entirely
> unacceptable. I however did not understand the proposal to be removing that
> capability, but instead I understood that it was simply adding another.
> That is, `Thing` would *still* be accepted. This feature is
> entirely additive.
>
> It would be great if the original proposal author could confirm this.
>
> Thanks,
> Jaden Geller
>
>
> ___
> 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] [Pitch] Enum with generic cases

2017-04-24 Thread Jaden Geller via swift-evolution

> On Apr 24, 2017, at 3:21 PM, Kevin Nattinger  wrote:
> 
> 
>> On Apr 24, 2017, at 3:16 PM, Jaden Geller > > wrote:
>> 
>> 
>>> On Apr 24, 2017, at 2:38 PM, Kevin Nattinger >> > wrote:
>>> 
 
 How can I improve your understanding?
 
>>> 
>>> 
>>> Given the enum I was using earlier:
>>> 
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(T)
>>> }
>>> 
>>> - Write a function that takes a thingOne or thingTwo but 
>>> nothing else.
>> 
>> This isn’t possible since generic types introduced on cases are erased in 
>> the type of `Thing`.
>> 
>> We can actually already achieve what you want by moving the generics onto 
>> the type itself, and this is already possible in Swift! No new features are 
>> necessary.
>> 
>> ```
>> enum Thing {
>> case thingOne(T1)
>> case thingTwo(T2)
>> }
>> 
>> func test(_ x: Thing) {
>> switch x {
>> case .thingOne(let s):
>> print("The string has value \(s)!")
>> case .thingTwo(let i):
>> print("The int has value \(i)!")
>> }
>> }
>> ```
> 
> Yes, that was almost exactly my original example. My understanding of the 
> proposal is that it will remove that capability, which I find completely 
> unacceptable.
> 

Hi Kevin,

If that is what is being proposed, I agree that that is entirely unacceptable. 
I however did not understand the proposal to be removing that capability, but 
instead I understood that it was simply adding another. That is, `Thing` would *still* be accepted. This feature is entirely additive.

It would be great if the original proposal author could confirm this.

Thanks,
Jaden Geller

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


Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Kevin Nattinger via swift-evolution

> On Apr 24, 2017, at 3:16 PM, Jaden Geller  wrote:
> 
> 
>> On Apr 24, 2017, at 2:38 PM, Kevin Nattinger > > wrote:
>> 
>>> 
>>> How can I improve your understanding?
>>> 
>> 
>> 
>> Given the enum I was using earlier:
>> 
>> enum Thing {
>> case thingOne(T)
>> case thingTwo(T)
>> }
>> 
>> - Write a function that takes a thingOne or thingTwo but 
>> nothing else.
> 
> This isn’t possible since generic types introduced on cases are erased in the 
> type of `Thing`.
> 
> We can actually already achieve what you want by moving the generics onto the 
> type itself, and this is already possible in Swift! No new features are 
> necessary.
> 
> ```
> enum Thing {
> case thingOne(T1)
> case thingTwo(T2)
> }
> 
> func test(_ x: Thing) {
> switch x {
> case .thingOne(let s):
> print("The string has value \(s)!")
> case .thingTwo(let i):
> print("The int has value \(i)!")
> }
> }
> ```

Yes, that was almost exactly my original example. My understanding of the 
proposal is that it will remove that capability, which I find completely 
unacceptable.

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


Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Jaden Geller via swift-evolution

> On Apr 24, 2017, at 2:38 PM, Kevin Nattinger  wrote:
> 
>> 
>> How can I improve your understanding?
>> 
> 
> 
> Given the enum I was using earlier:
> 
> enum Thing {
> case thingOne(T)
> case thingTwo(T)
> }
> 
> - Write a function that takes a thingOne or thingTwo but nothing 
> else.

This isn’t possible since generic types introduced on cases are erased in the 
type of `Thing`.

We can actually already achieve what you want by moving the generics onto the 
type itself, and this is already possible in Swift! No new features are 
necessary.

```
enum Thing {
case thingOne(T1)
case thingTwo(T2)
}

func test(_ x: Thing) {
switch x {
case .thingOne(let s):
print("The string has value \(s)!")
case .thingTwo(let i):
print("The int has value \(i)!")
}
}
```

> - Declare a variable that can hold a thingOne or thingTwo but 
> nothing else.

With our new definition, we can write:

```
var x: Thing
```

This variable can be initialized with a `thingOne` containing a `String` 
payload or a `thingTwo` containing an `Int` payload.

> Or explain why something that is widely used, trivial to write, and necessary 
> for type safety should be removed from the language.

As I just explained, what you desire is *already possible* in the language. 
This new features does not address your use case. Instead, this feature allows 
for type erasure of enum cases. This is pretty similar to storing an 
existential as a payload. I’m not even sure if it’s sufficiently different to 
justify its addition to the language.

The original non-generic definition of `Thing` with generic cases is 
essentially equivalent to storying `Any` as the case payloads. We can make this 
more useful by using protocols to constrain the payload type.

I think this proposal doesn’t really add any useful new capabilities without 
the ability to constraint the return type. For example, these are nearly 
equivalent:

```
enum Key {
case hashable(T)
case any(T)
}
```

vs.

```
enum Key {
case hashable(AnyHashable)
case any(Any)
}
```

Both of these definitions are nearly equivalent except the former introduces a 
new generic variable in scope when you match on a constrained case. Is this 
useful? I’m not sure. Is it breaking type safety? Absolutely not!! If I match 
the `hashable` case in a switch statement, it’s very similar to if I had 
written a function with the following signature:

```
func matchHashable(_ x: T) { ... }
```

Because of this, no type safety is lost in the switch statement.

—

I think a more interesting version of this proposal would be as follows: Allow 
where constraints and explicit return type annotations on case declarations. 
This is very similar to what a GADT 
 allows you to do. Check out how 
cool this example is—and 110% type-safe!

Below is an example of a data structure representing a computation. We can 
inspect is since it is just data, but we can also evaluate it to see the result.

```
enum Expression {
case value(T)
case isEqual(T, T) -> Expression where T: Equatable
case plus(T, T) -> Expression where T: Numeric
case and(Bool, Bool) -> Expression
case not(Bool) -> Expression
// etc.

func evaluate() -> T {
switch self {
case .value(let x):
return x
case .isEqual(let lhs, let rhs):
// We know that T: Equatable, so we can use `==`
return lhs == rhs
case .plus(let lhs, let rhs):
// We know that T: Numeric, so we can use `+`
return lhs + rhs
case .and(let lhs, let rhs):
return lhs && rhs
case .not(let x):
return !x
}
}
}

let x: Expression = .plus(.value(3), .value(10))
let y: Expression = .plus(.value(7), .value(6))
let z: Expression = .isEqual(x, y)

print(z.evaluate()) // -> true
```

Notice that it is impossible to construct an `Expression` of a nonsensical 
type. Try to do this with the enums we have in Swift today. You’ll have to do 
some force casting of types. Not pretty.

—

I hope I was able to clarify some things for you. Let me know if you have any 
other questions.

Cheers,
Jaden Geller

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


Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Joshua Alvarado via swift-evolution
>func handle() {
> switch self {
> case .thingOne(let s):
> if T is String {
> // s is of type String
> } else {
> // default case!
> }
> case .thingTwo(let i):
> if U is Int {
> // i is an Int
> } else {
> // default case!
> }
> }
> }

This would definitely be the default case if the generics don't have any 
constraints on them but the proposal is to make generics in enumerated better 
so that the above won't be needed they will just be used based on their 
constraints and no need to type cast (that would be the goal). 

Alvarado, Joshua

> On Apr 24, 2017, at 3:46 PM, Jaden Geller  wrote:
> 
> 
>> On Apr 24, 2017, at 2:33 PM, Joshua Alvarado  
>> wrote:
>> 
>> Hmmm interesting point it would be good to consider this and get to an 
>> implementation that helps cover both or just implement the desired feature 
>> and in the future add more resiliency. 
>> 
>> Alvarado, Joshua
>> 
>>> On Apr 24, 2017, at 2:41 PM, Jaden Geller  wrote:
>>> 
>>> 
 On Apr 24, 2017, at 1:34 PM, Joshua Alvarado via swift-evolution 
  wrote:
 
 Well in your case thing one and thing two will be the same type as you are 
 using the same T generic type on both.
 
 To achieve your case you can do an extension on the enum and use two 
 different generics:
 
 enum Thing {
 case thingOne(T)
 case thingTwo(U)
 }
 
 extension Thing where T == String, U == Int {
func handle(thing: Thing) {
 switch thing {
 case thingOne(let s):
 // s is type String
 
 case thingTwo(let i):
 // i is an Int
 }
}
 }
> 
> I think it’s important to not that the above example (without generic 
> information carried with the type) should not be able to provide an extension 
> that constrains the type. The problem is that, since we don’t know what `T` 
> and `U` actually are for an arbitrary instance at compile-time, we cannot 
> ensure that `handle` is not called when `T` and `U` don’t match the 
> extension. We’d have to require an implementation of `handle` for every 
> possible type. I guess it _could_ be reasonable to allow such a constrained 
> extension if we already defined `handle` for any `T` and `U`, but this 
> implementation would probably be simple (and equivalent after optimization):
> 
> ```
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> 
> func handle() {
> switch self {
> case .thingOne(let s):
> if T is String {
> // s is of type String
> } else {
> // default case!
> }
> case .thingTwo(let i):
> if U is Int {
> // i is an Int
> } else {
> // default case!
> }
> }
> }
> }
> ```
> 
> Cheers,
> Jaden Geller
> 
 
 This can actually be achieved in Swift 3.1, you can run this in a 
 playground.
>>> 
>>> This is not quite the same. In the original example, the type information 
>>> was thrown away after an instance of type `Foo` was constructed.
>>> 
>>> Here’s an example that wouldn’t work in your model:
>>> 
>>> ```
>>> enum Whatever {
>>> case some(T)
>>> }
>>> 
>>> var x: Whatever = .some(3)
>>> x = .some([1, 2, 3])
>>> ```
>>> 
>>> If `Whatever` was generic in `T`, then a variable can only store case 
>>> payloads with that specific type. I guess this could be worked around by 
>>> introducing a `AnyWhatever` protocol, but still, it’s not an identical 
>>> feature.
>>> 
>>> That said, it might be true that this isn’t actually a desirable feature. 
>>> We ought to definitely consider the implications of it and any 
>>> alternatives. Thanks for mentioning this, it’s a decent workaround 
>>> dependent on what you’d like to accomplish!
>>> 
>>> Cheers,
>>> Jaden Geller
>>> 
 
 enum Foo {
 case bar(obj: T)
 case baz(obj: U)
 
 func handle() {
 switch self {
 case .bar(obj: let x):
 break
 case .baz(obj: let y):
 break
 }
 }
 }
 
 extension Foo where T == String, U == Int {
 func handle() {
 switch self {
 case .bar(obj: let str):
 print(str)
 case .baz(obj: let aNum):
 print(aNum)
 }
 }
 }
 
 let foo = Foo.baz(obj: 1)
 foo.handle() // prints 1
 
 
 
> On Mon, Apr 24, 2017 at 2:15 PM, Kevin Nattinger  
> wrote:
> This makes it more convenient to create them, sure, but how would you 
> pass them around or 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Kevin Nattinger via swift-evolution
> 
> How can I improve your understanding?
> 


Given the enum I was using earlier:

enum Thing {
case thingOne(T)
case thingTwo(T)
}

- Write a function that takes a thingOne or thingTwo but nothing 
else.
- Declare a variable that can hold a thingOne or thingTwo but 
nothing else.

Or explain why something that is widely used, trivial to write, and necessary 
for type safety should be removed from the language.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Jaden Geller via swift-evolution

> On Apr 24, 2017, at 2:33 PM, Joshua Alvarado  
> wrote:
> 
> Hmmm interesting point it would be good to consider this and get to an 
> implementation that helps cover both or just implement the desired feature 
> and in the future add more resiliency. 
> 
> Alvarado, Joshua
> 
> On Apr 24, 2017, at 2:41 PM, Jaden Geller  > wrote:
> 
>> 
>>> On Apr 24, 2017, at 1:34 PM, Joshua Alvarado via swift-evolution 
>>> > wrote:
>>> 
>>> Well in your case thing one and thing two will be the same type as you are 
>>> using the same T generic type on both.
>>> 
>>> To achieve your case you can do an extension on the enum and use two 
>>> different generics:
>>> 
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(U)
>>> }
>>> 
>>> extension Thing where T == String, U == Int {
>>>func handle(thing: Thing) {
>>> switch thing {
>>> case thingOne(let s):
>>> // s is type String
>>> 
>>> case thingTwo(let i):
>>> // i is an Int
>>> }
>>>}
>>> }

I think it’s important to not that the above example (without generic 
information carried with the type) should not be able to provide an extension 
that constrains the type. The problem is that, since we don’t know what `T` and 
`U` actually are for an arbitrary instance at compile-time, we cannot ensure 
that `handle` is not called when `T` and `U` don’t match the extension. We’d 
have to require an implementation of `handle` for every possible type. I guess 
it _could_ be reasonable to allow such a constrained extension if we already 
defined `handle` for any `T` and `U`, but this implementation would probably be 
simple (and equivalent after optimization):

```
enum Thing {
case thingOne(T)
case thingTwo(U)

func handle() {
switch self {
case .thingOne(let s):
if T is String {
// s is of type String
} else {
// default case!
}
case .thingTwo(let i):
if U is Int {
// i is an Int
} else {
// default case!
}
}
}
}
```

Cheers,
Jaden Geller

>>> 
>>> This can actually be achieved in Swift 3.1, you can run this in a 
>>> playground.
>> 
>> This is not quite the same. In the original example, the type information 
>> was thrown away after an instance of type `Foo` was constructed.
>> 
>> Here’s an example that wouldn’t work in your model:
>> 
>> ```
>> enum Whatever {
>> case some(T)
>> }
>> 
>> var x: Whatever = .some(3)
>> x = .some([1, 2, 3])
>> ```
>> 
>> If `Whatever` was generic in `T`, then a variable can only store case 
>> payloads with that specific type. I guess this could be worked around by 
>> introducing a `AnyWhatever` protocol, but still, it’s not an identical 
>> feature.
>> 
>> That said, it might be true that this isn’t actually a desirable feature. We 
>> ought to definitely consider the implications of it and any alternatives. 
>> Thanks for mentioning this, it’s a decent workaround dependent on what you’d 
>> like to accomplish!
>> 
>> Cheers,
>> Jaden Geller
>> 
>>> 
>>> enum Foo {
>>> case bar(obj: T)
>>> case baz(obj: U)
>>> 
>>> func handle() {
>>> switch self {
>>> case .bar(obj: let x):
>>> break
>>> case .baz(obj: let y):
>>> break
>>> }
>>> }
>>> }
>>> 
>>> extension Foo where T == String, U == Int {
>>> func handle() {
>>> switch self {
>>> case .bar(obj: let str):
>>> print(str)
>>> case .baz(obj: let aNum):
>>> print(aNum)
>>> }
>>> }
>>> }
>>> 
>>> let foo = Foo.baz(obj: 1)
>>> foo.handle() // prints 1
>>> 
>>> 
>>> 
>>> On Mon, Apr 24, 2017 at 2:15 PM, Kevin Nattinger >> > wrote:
>>> This makes it more convenient to create them, sure, but how would you pass 
>>> them around or extract the value in a type-safe manner?
>>> 
>>> e.g. now I can write:
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(U)
>>> }
>>> 
>>> // How do I require thingOne or thingTwo?
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case .thingOne(let s): print("string \(s)")
>>> case .thingTwo(let i): print("int \(i)")
>>> }
>>> }
>>> 
>>> With your proposed syntax:
>>> 
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(T)
>>> }
>>> 
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case thingOne(let s):
>>> // What is the type of s?
>>> case thingTwo(let i):
>>> // is it even possible to write an exhaustive switch?
>>> }
>>> }
>>> 
>>> 
>>> 
 On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Joshua Alvarado via swift-evolution
Yeah I was implying that T would be the same generic for both so that is a good 
point for my proposal they would have to be disconnected or maybe he complier 
can infer that the two generics are the same within the same enum scope. 

A way to create a variable of thing one with an aunt or string only would be to 
use a case let but it would have to be two spectate cases and not just one 
variable. 

If case let .thingOne(str as String) {

}

If case let .thingOne(aNum as Int) {

}

Alvarado, Joshua

> On Apr 24, 2017, at 2:56 PM, Kevin Nattinger  wrote:
> 
> 
>> On Apr 24, 2017, at 1:34 PM, Joshua Alvarado  
>> wrote:
>> 
>> Well in your case thing one and thing two will be the same type as you are 
>> using the same T generic type on both.
> 
> It’s two different and unrelated generics unless you’re intending to change 
> the way generics work entirely.
> 
> func foo(x: T)
> func bar(x: T)
> They both use “T” as the generic, but the T’s are unrelated.  
> 
> You can even have a generic function type shadow the containing class’s 
> generic type:
> 
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> 
> func foo(x: T) -> T { return x }
> }
> 
> let x = Thing.thingOne("").foo(x: [5.0])
> type(of: x) // Array.Type 
> 
> (Not recommended, obviously, just demonstrating that generic types are 
> independent regardless of the name)
> 
>> 
>> To achieve your case you can do an extension on the enum and use two 
>> different generics:
>> 
>> enum Thing {
>> case thingOne(T)
>> case thingTwo(U)
>> }
>> 
>> extension Thing where T == String, U == Int {
> 
> Ah, but there is no T or U on the enum, just on the cases. And what if the 
> function needs to be in another class for encapsulation reasons? 
> Furthermore, how would you even call this function? How do you create a 
> variable that can hold either a thingOne with a string or a thingTwo with an 
> Int, and nothing else?
> 
>>func handle(thing: Thing) {
>> switch thing {
>> case thingOne(let s):
>> // s is type String
>> 
>> case thingTwo(let i):
>> // i is an Int
>> }
>>}
>> }
>> 
>> This can actually be achieved in Swift 3.1, you can run this in a playground.
>> 
>> enum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> 
>> func handle() {
>> switch self {
>> case .bar(obj: let x):
>> break
>> case .baz(obj: let y):
>> break
>> }
>> }
>> }
>> 
>> extension Foo where T == String, U == Int {
>> func handle() {
>> switch self {
>> case .bar(obj: let str):
>> print(str)
>> case .baz(obj: let aNum):
>> print(aNum)
>> }
>> }
>> }
>> 
>> let foo = Foo.baz(obj: 1)
>> foo.handle() // prints 1
>> 
>> 
>> 
>>> On Mon, Apr 24, 2017 at 2:15 PM, Kevin Nattinger  
>>> wrote:
>>> This makes it more convenient to create them, sure, but how would you pass 
>>> them around or extract the value in a type-safe manner?
>>> 
>>> e.g. now I can write:
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(U)
>>> }
>>> 
>>> // How do I require thingOne or thingTwo?
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case .thingOne(let s): print("string \(s)")
>>> case .thingTwo(let i): print("int \(i)")
>>> }
>>> }
>>> 
>>> With your proposed syntax:
>>> 
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(T)
>>> }
>>> 
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case thingOne(let s):
>>> // What is the type of s?
>>> case thingTwo(let i):
>>> // is it even possible to write an exhaustive switch?
>>> }
>>> }
>>> 
>>> 
>>> 
 On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
  wrote:
 
 Here is my pitch on adding generics to enum cases and not to the enum type 
 itself. Let me know if you have an improvements or modifications lets open 
 it to discussion thank you swiftys! :)
 Enum with generic cases
 Proposal: SE-
 Authors: Joshua Alvarado
 Review Manager: TBD
 Status: PITCH
 During the review process, add the following fields as needed:
 
 Decision Notes: Rationale, Additional Commentary
 Bugs: SR-, SR-
 Previous Revision: 1
 Previous Proposal: SE-
 Introduction
 
 This proposal adds a change to the enumeration type that allows an enum 
 case to cast a generic on its associated value.
 
 Swift-evolution thread: Discussion thread topic for that proposal
 
 Motivation
 
 Enums currently support generics, but they are added onto the type itself. 
 This can cause adverse syntax when implementing generics for associated 
 values to be stored along each case. The enum case holds the associated 
 value (not 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Joshua Alvarado via swift-evolution
Hmmm interesting point it would be good to consider this and get to an 
implementation that helps cover both or just implement the desired feature and 
in the future add more resiliency. 

Alvarado, Joshua

> On Apr 24, 2017, at 2:41 PM, Jaden Geller  wrote:
> 
> 
>> On Apr 24, 2017, at 1:34 PM, Joshua Alvarado via swift-evolution 
>>  wrote:
>> 
>> Well in your case thing one and thing two will be the same type as you are 
>> using the same T generic type on both.
>> 
>> To achieve your case you can do an extension on the enum and use two 
>> different generics:
>> 
>> enum Thing {
>> case thingOne(T)
>> case thingTwo(U)
>> }
>> 
>> extension Thing where T == String, U == Int {
>>func handle(thing: Thing) {
>> switch thing {
>> case thingOne(let s):
>> // s is type String
>> 
>> case thingTwo(let i):
>> // i is an Int
>> }
>>}
>> }
>> 
>> This can actually be achieved in Swift 3.1, you can run this in a playground.
> 
> This is not quite the same. In the original example, the type information was 
> thrown away after an instance of type `Foo` was constructed.
> 
> Here’s an example that wouldn’t work in your model:
> 
> ```
> enum Whatever {
> case some(T)
> }
> 
> var x: Whatever = .some(3)
> x = .some([1, 2, 3])
> ```
> 
> If `Whatever` was generic in `T`, then a variable can only store case 
> payloads with that specific type. I guess this could be worked around by 
> introducing a `AnyWhatever` protocol, but still, it’s not an identical 
> feature.
> 
> That said, it might be true that this isn’t actually a desirable feature. We 
> ought to definitely consider the implications of it and any alternatives. 
> Thanks for mentioning this, it’s a decent workaround dependent on what you’d 
> like to accomplish!
> 
> Cheers,
> Jaden Geller
> 
>> 
>> enum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> 
>> func handle() {
>> switch self {
>> case .bar(obj: let x):
>> break
>> case .baz(obj: let y):
>> break
>> }
>> }
>> }
>> 
>> extension Foo where T == String, U == Int {
>> func handle() {
>> switch self {
>> case .bar(obj: let str):
>> print(str)
>> case .baz(obj: let aNum):
>> print(aNum)
>> }
>> }
>> }
>> 
>> let foo = Foo.baz(obj: 1)
>> foo.handle() // prints 1
>> 
>> 
>> 
>>> On Mon, Apr 24, 2017 at 2:15 PM, Kevin Nattinger  
>>> wrote:
>>> This makes it more convenient to create them, sure, but how would you pass 
>>> them around or extract the value in a type-safe manner?
>>> 
>>> e.g. now I can write:
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(U)
>>> }
>>> 
>>> // How do I require thingOne or thingTwo?
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case .thingOne(let s): print("string \(s)")
>>> case .thingTwo(let i): print("int \(i)")
>>> }
>>> }
>>> 
>>> With your proposed syntax:
>>> 
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(T)
>>> }
>>> 
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case thingOne(let s):
>>> // What is the type of s?
>>> case thingTwo(let i):
>>> // is it even possible to write an exhaustive switch?
>>> }
>>> }
>>> 
>>> 
>>> 
 On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
  wrote:
 
 Here is my pitch on adding generics to enum cases and not to the enum type 
 itself. Let me know if you have an improvements or modifications lets open 
 it to discussion thank you swiftys! :)
 Enum with generic cases
 Proposal: SE-
 Authors: Joshua Alvarado
 Review Manager: TBD
 Status: PITCH
 During the review process, add the following fields as needed:
 
 Decision Notes: Rationale, Additional Commentary
 Bugs: SR-, SR-
 Previous Revision: 1
 Previous Proposal: SE-
 Introduction
 
 This proposal adds a change to the enumeration type that allows an enum 
 case to cast a generic on its associated value.
 
 Swift-evolution thread: Discussion thread topic for that proposal
 
 Motivation
 
 Enums currently support generics, but they are added onto the type itself. 
 This can cause adverse syntax when implementing generics for associated 
 values to be stored along each case. The enum case holds the associated 
 value (not the enum type itself) so should create its own value 
 constraints.
 
 Proposed solution
 
 The generic is to be casted on the case of the enum and not on the enum 
 itself.
 
 Detailed design
 
 Current implementation:
 
 // enum with two generic types
 enum Foo {
 case bar(obj: T)
 case baz(obj: U)
 }
 
 // U is to 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Jaden Geller via swift-evolution


> On Apr 24, 2017, at 2:09 PM, Kevin Nattinger  wrote:
> 
> 
>>> On Apr 24, 2017, at 1:36 PM, Jaden Geller  wrote:
>>> 
>>> 
>>> On Apr 24, 2017, at 1:15 PM, Kevin Nattinger via swift-evolution 
>>>  wrote:
>>> 
>>> This makes it more convenient to create them, sure, but how would you pass 
>>> them around or extract the value in a type-safe manner?
>> 
>> If the case introduces a generic type, than the switching over that case 
>> introduces a generic type variable in that scope.
> 
> I don’t want a generic type, I want to be able to specify exactly what types 
> the function accepts. 

Generic cases are exactly what I understand to be proposed. Can you explain how 
what you're looking for differs?

> 
>> 
>>> 
>>> e.g. now I can write:
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(U)
>>> }
>>> 
>>> // How do I require thingOne or thingTwo?
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case .thingOne(let s): print("string \(s)")
>>> case .thingTwo(let i): print("int \(i)")
>>> }
>>> }
>>> 
>>> With your proposed syntax:
>>> 
>>> enum Thing {
>>> case thingOne(T)
>>> case thingTwo(T)
>>> }
>>> 
>>> func handle(thing: Thing) {
>>> switch thing {
>>> case thingOne(let s):
>>> // What is the type of s?
>> 
>> It is some new generic variable `T`. It might be best to require that it is 
>> explicitly introduced:
>> ```
>> case thingOne(let s):
>> ```
>> You could use `s` like you could use `x` in `func (x: T) { … }`. That’s 
>> to say that you couldn’t do much with it. You could store it in an `Any`. 
>> You could dynamically check the type. You could ignore it. You could print 
>> it.
> 
> So what good is a value I can’t do anything with?

It's not particularly useful BECAUSE you didn't specify any generic 
constraints. Just like a generic function, you can only do with a value what 
it's constraints allow.

> 
>> 
>> It becomes a lot more useful when there are constraints on `T` in the 
>> original case definition of the type. For example, if `case thingOne> FloatingPoint>(T)` were written in the original enum definition, you could 
>> do anything with `s` that you could do with a `FloatingPoint`.
>> 
>>> case thingTwo(let i):
>>> // is it even possible to write an exhaustive switch?
>> 
>> Sure, but this switch isn’t yet exhaustive. You’d also have to add another 
>> case:
>> ```
>> case thingTwo(let i):
>> ```
> 
> In my original code, the function specifies exactly what it can handle, and 
> that restriction is enforced by the compiler. Do

Your switch statement wasn't exhaustive. You need to add an additional case 
that handles a T that isn't an Int (because it might not be one)! Swift cannot 
statically know the payload since it isn't part of the type. The case generics 
are erased, and you need to use case matching to bring them back.

> you really think it would be an improvement to remove compile-time type 
> restrictions? We may as well get rid of the type system and duck-type like 
> python. At least that would speed up type-inference bottlenecks.

That's entirely not what I advocated. I don't appreciate you strawmanning my 
explanation.

The model I explained is consistent with Swift's current type checking. It 
certainly does not remove any restrictions or add duck typing.

How can I improve your understanding?

> 
>> When we do come back to this proposal, it might be reasonable to leave these 
>> sorts of specializations (e.g. `case thingTwo`) out of the initial 
>> design since they might significantly complicate the model and they are 
>> entirely additive. I’m not sure though, I’m not familiar with the 
>> implementation.
>> 
>>> }
>>> }
>>> 
>> 
>> I’d really love to see GADTs in Swift, even if in a more limited form! 
>> Another GADT feature that would be nice to add (though probably would 
>> deserve a separate, later proposal) would be specialized generic return 
>> types for each case:
>> 
>> ```
>> enum Expr {
>> case value(T) -> Expr
>> case plus(Expr, Expr) -> Expr
>> case and(Expr, Expr) -> Expr
>> case equals(Expr, Expr) -> Expr where T: Equatable
>> }
>> ```
>> 
>> But ya, I realize this is a very major complication of the model… Would be 
>> so cool though!
>> 
>> This is all definitely out of scope for Swift 4, and likely out of scope for 
>> Swift 5 even… I guess we’ll find out once we get there. Still fun to think 
>> about!
>> 
>> Cheers,
>> Jaden Geller
>> 
>>> 
>>> 
 On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
  wrote:
 
 Here is my pitch on adding generics to enum cases and not to the enum type 
 itself. Let me know if you have an improvements or modifications lets open 
 it to discussion thank you swiftys! :)
 
 Enum with generic cases
 
 Proposal: SE-
 Authors: Joshua Alvarado

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Kevin Nattinger via swift-evolution

> On Apr 24, 2017, at 1:36 PM, Jaden Geller  wrote:
> 
>> 
>> On Apr 24, 2017, at 1:15 PM, Kevin Nattinger via swift-evolution 
>> > wrote:
>> 
>> This makes it more convenient to create them, sure, but how would you pass 
>> them around or extract the value in a type-safe manner?
> 
> If the case introduces a generic type, than the switching over that case 
> introduces a generic type variable in that scope.

I don’t want a generic type, I want to be able to specify exactly what types 
the function accepts. 

> 
>> 
>> e.g. now I can write:
>> enum Thing {
>> case thingOne(T)
>> case thingTwo(U)
>> }
>> 
>> // How do I require thingOne or thingTwo?
>> func handle(thing: Thing) {
>> switch thing {
>> case .thingOne(let s): print("string \(s)")
>> case .thingTwo(let i): print("int \(i)")
>> }
>> }
>> 
>> With your proposed syntax:
>> 
>> enum Thing {
>> case thingOne(T)
>> case thingTwo(T)
>> }
>> 
>> func handle(thing: Thing) {
>> switch thing {
>> case thingOne(let s):
>> // What is the type of s?
> 
> It is some new generic variable `T`. It might be best to require that it is 
> explicitly introduced:
> ```
> case thingOne(let s):
> ```
> You could use `s` like you could use `x` in `func (x: T) { … }`. That’s to 
> say that you couldn’t do much with it. You could store it in an `Any`. You 
> could dynamically check the type. You could ignore it. You could print it.

So what good is a value I can’t do anything with?

> 
> It becomes a lot more useful when there are constraints on `T` in the 
> original case definition of the type. For example, if `case thingOne FloatingPoint>(T)` were written in the original enum definition, you could do 
> anything with `s` that you could do with a `FloatingPoint`.
> 
>> case thingTwo(let i):
>> // is it even possible to write an exhaustive switch?
> 
> Sure, but this switch isn’t yet exhaustive. You’d also have to add another 
> case:
> ```
> case thingTwo(let i):
> ```

In my original code, the function specifies exactly what it can handle, and 
that restriction is enforced by the compiler. Do you really think it would be 
an improvement to remove compile-time type restrictions? We may as well get rid 
of the type system and duck-type like python. At least that would speed up 
type-inference bottlenecks.

> When we do come back to this proposal, it might be reasonable to leave these 
> sorts of specializations (e.g. `case thingTwo`) out of the initial 
> design since they might significantly complicate the model and they are 
> entirely additive. I’m not sure though, I’m not familiar with the 
> implementation.
> 
>> }
>> }
>> 
> 
> I’d really love to see GADTs in Swift, even if in a more limited form! 
> Another GADT feature that would be nice to add (though probably would deserve 
> a separate, later proposal) would be specialized generic return types for 
> each case:
> 
> ```
> enum Expr {
> case value(T) -> Expr
> case plus(Expr, Expr) -> Expr
> case and(Expr, Expr) -> Expr
> case equals(Expr, Expr) -> Expr where T: Equatable
> }
> ```
> 
> But ya, I realize this is a very major complication of the model… Would be so 
> cool though!
> 
> This is all definitely out of scope for Swift 4, and likely out of scope for 
> Swift 5 even… I guess we’ll find out once we get there. Still fun to think 
> about!
> 
> Cheers,
> Jaden Geller
> 
>> 
>> 
>>> On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
>>> > wrote:
>>> 
>>> Here is my pitch on adding generics to enum cases and not to the enum type 
>>> itself. Let me know if you have an improvements or modifications lets open 
>>> it to discussion thank you swiftys! :)
>>> 
>>> Enum with generic cases
>>> 
>>> Proposal: SE- 
>>> 
>>> Authors: Joshua Alvarado 
>>> Review Manager: TBD
>>> Status: PITCH
>>> During the review process, add the following fields as needed:
>>> 
>>> Decision Notes: Rationale 
>>> , Additional Commentary 
>>> 
>>> Bugs: SR- , SR- 
>>> 
>>> Previous Revision: 1 
>>> 
>>> Previous Proposal: SE- 
>>> 
>>>  
>>> Introduction
>>> 
>>> This proposal adds a change to the enumeration type that allows an enum 
>>> case to cast a generic on its associated value.
>>> 
>>> 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Kevin Nattinger via swift-evolution

> On Apr 24, 2017, at 1:34 PM, Joshua Alvarado  
> wrote:
> 
> Well in your case thing one and thing two will be the same type as you are 
> using the same T generic type on both.

It’s two different and unrelated generics unless you’re intending to change the 
way generics work entirely.

func foo(x: T)
func bar(x: T)
They both use “T” as the generic, but the T’s are unrelated.  

You can even have a generic function type shadow the containing class’s generic 
type:

enum Thing {
case thingOne(T)
case thingTwo(U)

func foo(x: T) -> T { return x }
}

let x = Thing.thingOne("").foo(x: [5.0])
type(of: x) // Array.Type 

(Not recommended, obviously, just demonstrating that generic types are 
independent regardless of the name)

> 
> To achieve your case you can do an extension on the enum and use two 
> different generics:
> 
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> }
> 
> extension Thing where T == String, U == Int {

Ah, but there is no T or U on the enum, just on the cases. And what if the 
function needs to be in another class for encapsulation reasons? 
Furthermore, how would you even call this function? How do you create a 
variable that can hold either a thingOne with a string or a thingTwo with an 
Int, and nothing else?

>func handle(thing: Thing) {
> switch thing {
> case thingOne(let s):
> // s is type String
> 
> case thingTwo(let i):
> // i is an Int
> }
>}
> }
> 
> This can actually be achieved in Swift 3.1, you can run this in a playground.
> 
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> 
> func handle() {
> switch self {
> case .bar(obj: let x):
> break
> case .baz(obj: let y):
> break
> }
> }
> }
> 
> extension Foo where T == String, U == Int {
> func handle() {
> switch self {
> case .bar(obj: let str):
> print(str)
> case .baz(obj: let aNum):
> print(aNum)
> }
> }
> }
> 
> let foo = Foo.baz(obj: 1)
> foo.handle() // prints 1
> 
> 
> 
> On Mon, Apr 24, 2017 at 2:15 PM, Kevin Nattinger  > wrote:
> This makes it more convenient to create them, sure, but how would you pass 
> them around or extract the value in a type-safe manner?
> 
> e.g. now I can write:
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> }
> 
> // How do I require thingOne or thingTwo?
> func handle(thing: Thing) {
> switch thing {
> case .thingOne(let s): print("string \(s)")
> case .thingTwo(let i): print("int \(i)")
> }
> }
> 
> With your proposed syntax:
> 
> enum Thing {
> case thingOne(T)
> case thingTwo(T)
> }
> 
> func handle(thing: Thing) {
> switch thing {
> case thingOne(let s):
> // What is the type of s?
> case thingTwo(let i):
> // is it even possible to write an exhaustive switch?
> }
> }
> 
> 
> 
>> On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
>> > wrote:
>> 
>> Here is my pitch on adding generics to enum cases and not to the enum type 
>> itself. Let me know if you have an improvements or modifications lets open 
>> it to discussion thank you swiftys! :)
>> 
>> Enum with generic cases
>> 
>> Proposal: SE- 
>> 
>> Authors: Joshua Alvarado 
>> Review Manager: TBD
>> Status: PITCH
>> During the review process, add the following fields as needed:
>> 
>> Decision Notes: Rationale 
>> , Additional Commentary 
>> 
>> Bugs: SR- , SR- 
>> 
>> Previous Revision: 1 
>> 
>> Previous Proposal: SE- 
>> 
>>  
>> Introduction
>> 
>> This proposal adds a change to the enumeration type that allows an enum case 
>> to cast a generic on its associated value.
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal 
>> 
>>  
>> Motivation
>> 
>> Enums currently support generics, but they are added onto the type itself. 
>> This can cause adverse syntax when implementing generics for associated 
>> values to be stored along each case. The enum case holds the associated 
>> value (not the enum type itself) so should create 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Jaden Geller via swift-evolution

> On Apr 24, 2017, at 1:34 PM, Joshua Alvarado via swift-evolution 
>  wrote:
> 
> Well in your case thing one and thing two will be the same type as you are 
> using the same T generic type on both.
> 
> To achieve your case you can do an extension on the enum and use two 
> different generics:
> 
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> }
> 
> extension Thing where T == String, U == Int {
>func handle(thing: Thing) {
> switch thing {
> case thingOne(let s):
> // s is type String
> 
> case thingTwo(let i):
> // i is an Int
> }
>}
> }
> 
> This can actually be achieved in Swift 3.1, you can run this in a playground.

This is not quite the same. In the original example, the type information was 
thrown away after an instance of type `Foo` was constructed.

Here’s an example that wouldn’t work in your model:

```
enum Whatever {
case some(T)
}

var x: Whatever = .some(3)
x = .some([1, 2, 3])
```

If `Whatever` was generic in `T`, then a variable can only store case payloads 
with that specific type. I guess this could be worked around by introducing a 
`AnyWhatever` protocol, but still, it’s not an identical feature.

That said, it might be true that this isn’t actually a desirable feature. We 
ought to definitely consider the implications of it and any alternatives. 
Thanks for mentioning this, it’s a decent workaround dependent on what you’d 
like to accomplish!

Cheers,
Jaden Geller

> 
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> 
> func handle() {
> switch self {
> case .bar(obj: let x):
> break
> case .baz(obj: let y):
> break
> }
> }
> }
> 
> extension Foo where T == String, U == Int {
> func handle() {
> switch self {
> case .bar(obj: let str):
> print(str)
> case .baz(obj: let aNum):
> print(aNum)
> }
> }
> }
> 
> let foo = Foo.baz(obj: 1)
> foo.handle() // prints 1
> 
> 
> 
> On Mon, Apr 24, 2017 at 2:15 PM, Kevin Nattinger  > wrote:
> This makes it more convenient to create them, sure, but how would you pass 
> them around or extract the value in a type-safe manner?
> 
> e.g. now I can write:
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> }
> 
> // How do I require thingOne or thingTwo?
> func handle(thing: Thing) {
> switch thing {
> case .thingOne(let s): print("string \(s)")
> case .thingTwo(let i): print("int \(i)")
> }
> }
> 
> With your proposed syntax:
> 
> enum Thing {
> case thingOne(T)
> case thingTwo(T)
> }
> 
> func handle(thing: Thing) {
> switch thing {
> case thingOne(let s):
> // What is the type of s?
> case thingTwo(let i):
> // is it even possible to write an exhaustive switch?
> }
> }
> 
> 
> 
>> On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
>> > wrote:
>> 
>> Here is my pitch on adding generics to enum cases and not to the enum type 
>> itself. Let me know if you have an improvements or modifications lets open 
>> it to discussion thank you swiftys! :)
>> 
>> Enum with generic cases
>> 
>> Proposal: SE- 
>> 
>> Authors: Joshua Alvarado 
>> Review Manager: TBD
>> Status: PITCH
>> During the review process, add the following fields as needed:
>> 
>> Decision Notes: Rationale 
>> , Additional Commentary 
>> 
>> Bugs: SR- , SR- 
>> 
>> Previous Revision: 1 
>> 
>> Previous Proposal: SE- 
>> 
>>  
>> Introduction
>> 
>> This proposal adds a change to the enumeration type that allows an enum case 
>> to cast a generic on its associated value.
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal 
>> 
>>  
>> Motivation
>> 
>> Enums currently support generics, but they are added onto the type itself. 
>> This can cause adverse syntax when implementing generics for associated 
>> values to be stored along each case. The enum case holds the associated 
>> value (not the enum type itself) so should create its own value constraints.
>> 
>>  
>> 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Jaden Geller via swift-evolution

> On Apr 24, 2017, at 1:15 PM, Kevin Nattinger via swift-evolution 
>  wrote:
> 
> This makes it more convenient to create them, sure, but how would you pass 
> them around or extract the value in a type-safe manner?

If the case introduces a generic type, than the switching over that case 
introduces a generic type variable in that scope.

> 
> e.g. now I can write:
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> }
> 
> // How do I require thingOne or thingTwo?
> func handle(thing: Thing) {
> switch thing {
> case .thingOne(let s): print("string \(s)")
> case .thingTwo(let i): print("int \(i)")
> }
> }
> 
> With your proposed syntax:
> 
> enum Thing {
> case thingOne(T)
> case thingTwo(T)
> }
> 
> func handle(thing: Thing) {
> switch thing {
> case thingOne(let s):
> // What is the type of s?

It is some new generic variable `T`. It might be best to require that it is 
explicitly introduced:
```
case thingOne(let s):
```
You could use `s` like you could use `x` in `func (x: T) { … }`. That’s to 
say that you couldn’t do much with it. You could store it in an `Any`. You 
could dynamically check the type. You could ignore it. You could print it.

It becomes a lot more useful when there are constraints on `T` in the original 
case definition of the type. For example, if `case thingOne(T)` were written in the original enum definition, you could do 
anything with `s` that you could do with a `FloatingPoint`.

> case thingTwo(let i):
> // is it even possible to write an exhaustive switch?

Sure, but this switch isn’t yet exhaustive. You’d also have to add another case:
```
case thingTwo(let i):
```
When we do come back to this proposal, it might be reasonable to leave these 
sorts of specializations (e.g. `case thingTwo`) out of the initial design 
since they might significantly complicate the model and they are entirely 
additive. I’m not sure though, I’m not familiar with the implementation.

> }
> }
> 

I’d really love to see GADTs in Swift, even if in a more limited form! Another 
GADT feature that would be nice to add (though probably would deserve a 
separate, later proposal) would be specialized generic return types for each 
case:

```
enum Expr {
case value(T) -> Expr
case plus(Expr, Expr) -> Expr
case and(Expr, Expr) -> Expr
case equals(Expr, Expr) -> Expr where T: Equatable
}
```

But ya, I realize this is a very major complication of the model… Would be so 
cool though!

This is all definitely out of scope for Swift 4, and likely out of scope for 
Swift 5 even… I guess we’ll find out once we get there. Still fun to think 
about!

Cheers,
Jaden Geller

> 
> 
>> On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
>> > wrote:
>> 
>> Here is my pitch on adding generics to enum cases and not to the enum type 
>> itself. Let me know if you have an improvements or modifications lets open 
>> it to discussion thank you swiftys! :)
>> 
>> Enum with generic cases
>> 
>> Proposal: SE- 
>> 
>> Authors: Joshua Alvarado 
>> Review Manager: TBD
>> Status: PITCH
>> During the review process, add the following fields as needed:
>> 
>> Decision Notes: Rationale 
>> , Additional Commentary 
>> 
>> Bugs: SR- , SR- 
>> 
>> Previous Revision: 1 
>> 
>> Previous Proposal: SE- 
>> 
>>  
>> Introduction
>> 
>> This proposal adds a change to the enumeration type that allows an enum case 
>> to cast a generic on its associated value.
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal 
>> 
>>  
>> Motivation
>> 
>> Enums currently support generics, but they are added onto the type itself. 
>> This can cause adverse syntax when implementing generics for associated 
>> values to be stored along each case. The enum case holds the associated 
>> value (not the enum type itself) so should create its own value constraints.
>> 
>>  
>> Proposed
>>  solution
>> 
>> The generic is to be casted on the case of the enum and not on the enum 
>> itself.
>> 
>>  
>> 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Joshua Alvarado via swift-evolution
Well in your case thing one and thing two will be the same type as you are
using the same T generic type on both.

To achieve your case you can do an extension on the enum and use two
different generics:

enum Thing {
case thingOne(T)
case thingTwo(U)
}

extension Thing where T == String, U == Int {
   func handle(thing: Thing) {
switch thing {
case thingOne(let s):
// s is type String

case thingTwo(let i):
// i is an Int
}
   }
}

This can actually be achieved in Swift 3.1, you can run this in a
playground.

enum Foo {

case bar(obj: T)

case baz(obj: U)


func handle() {

switch self {

case .bar(obj: let x):

break

case .baz(obj: let y):

break

}

}

}


extension Foo where T == String, U == Int {

func handle() {

switch self {

case .bar(obj: let str):

print(str)

case .baz(obj: let aNum):

print(aNum)

}

}

}


let foo = Foo.baz(obj: 1)

foo.handle() // prints 1



On Mon, Apr 24, 2017 at 2:15 PM, Kevin Nattinger 
wrote:

> This makes it more convenient to create them, sure, but how would you pass
> them around or extract the value in a type-safe manner?
>
> e.g. now I can write:
> enum Thing {
> case thingOne(T)
> case thingTwo(U)
> }
>
> // How do I require thingOne or thingTwo?
> func handle(thing: Thing) {
> switch thing {
> case .thingOne(let s): print("string \(s)")
> case .thingTwo(let i): print("int \(i)")
> }
> }
>
> With your proposed syntax:
>
> enum Thing {
> case thingOne(T)
> case thingTwo(T)
> }
>
> func handle(thing: Thing) {
> switch thing {
> case thingOne(let s):
> // What is the type of s?
> case thingTwo(let i):
> // is it even possible to write an exhaustive switch?
> }
> }
>
>
>
> On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Here is my pitch on adding generics to enum cases and not to the enum type
> itself. Let me know if you have an improvements or modifications lets open
> it to discussion thank you swiftys! :)Enum with generic cases
>
>- Proposal: SE-
>
> 
>- Authors: Joshua Alvarado 
>- Review Manager: TBD
>- Status: PITCH
>
> *During the review process, add the following fields as needed:*
>
>- Decision Notes: Rationale
>, Additional
>Commentary 
>- Bugs: SR- , SR-
>
>- Previous Revision: 1
>
> 
>- Previous Proposal: SE-
>
> 
>
>
> 
> Introduction
>
> This proposal adds a change to the enumeration type that allows an enum
> case to cast a generic on its associated value.
>
> Swift-evolution thread: Discussion thread topic for that proposal
> 
> 
> Motivation
>
> Enums currently support generics, but they are added onto the type itself.
> This can cause adverse syntax when implementing generics for associated
> values to be stored along each case. The enum case holds the associated
> value (not the enum type itself) so should create its own value constraints.
>
> Proposed
> solution
>
> The generic is to be casted on the case of the enum and not on the enum
> itself.
>
> Detailed
> design
>
> Current implementation:
>
> // enum with two generic typesenum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> // U is to be casted but it is not even usedlet foo: Foo = 
> .bar(obj: "hash")
> // Creating an optional enum, the generics have to be casted without a value 
> set// The casting is really not needed as the values should be casted not the 
> enumvar foo1: Foo?
> // Collections don’t look great eithervar foos = [Foo]()
> foos.append(.bar(obj:"hash"))
>
> Proposed solution
>
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> // generic type inferred on Tvar foo: Foo = .bar(obj: "hash")
> // doesn’t need to cast the generic on the optional enum// the associated 
> value will hold the castvar foo1: Foo?
> // This also gives better syntax with 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Kevin Nattinger via swift-evolution
This makes it more convenient to create them, sure, but how would you pass them 
around or extract the value in a type-safe manner?

e.g. now I can write:
enum Thing {
case thingOne(T)
case thingTwo(U)
}

// How do I require thingOne or thingTwo?
func handle(thing: Thing) {
switch thing {
case .thingOne(let s): print("string \(s)")
case .thingTwo(let i): print("int \(i)")
}
}

With your proposed syntax:

enum Thing {
case thingOne(T)
case thingTwo(T)
}

func handle(thing: Thing) {
switch thing {
case thingOne(let s):
// What is the type of s?
case thingTwo(let i):
// is it even possible to write an exhaustive switch?
}
}



> On Apr 24, 2017, at 6:57 AM, Joshua Alvarado via swift-evolution 
>  wrote:
> 
> Here is my pitch on adding generics to enum cases and not to the enum type 
> itself. Let me know if you have an improvements or modifications lets open it 
> to discussion thank you swiftys! :)
> 
> Enum with generic cases
> 
> Proposal: SE- 
> 
> Authors: Joshua Alvarado 
> Review Manager: TBD
> Status: PITCH
> During the review process, add the following fields as needed:
> 
> Decision Notes: Rationale 
> , Additional Commentary 
> 
> Bugs: SR- , SR- 
> 
> Previous Revision: 1 
> 
> Previous Proposal: SE- 
> 
>  
> Introduction
> 
> This proposal adds a change to the enumeration type that allows an enum case 
> to cast a generic on its associated value.
> 
> Swift-evolution thread: Discussion thread topic for that proposal 
> 
>  
> Motivation
> 
> Enums currently support generics, but they are added onto the type itself. 
> This can cause adverse syntax when implementing generics for associated 
> values to be stored along each case. The enum case holds the associated value 
> (not the enum type itself) so should create its own value constraints.
> 
>  
> Proposed
>  solution
> 
> The generic is to be casted on the case of the enum and not on the enum 
> itself.
> 
>  
> Detailed
>  design
> 
> Current implementation:
> 
> // enum with two generic types
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> 
> // U is to be casted but it is not even used
> let foo: Foo = .bar(obj: "hash")
> 
> // Creating an optional enum, the generics have to be casted without a value 
> set
> // The casting is really not needed as the values should be casted not the 
> enum
> var foo1: Foo?
> 
> // Collections don’t look great either
> var foos = [Foo]()
> foos.append(.bar(obj:"hash"))
> Proposed solution
> 
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> 
> // generic type inferred on T
> var foo: Foo = .bar(obj: "hash") 
> 
> // doesn’t need to cast the generic on the optional enum
> // the associated value will hold the cast
> var foo1: Foo? 
> 
> // This also gives better syntax with collections of enums with associated 
> types
> var foos = [Foo]()
> foos.append(.bar(obj: "hey")
>  
> Source
>  compatibility
> 
> This may cause subtle breaking changes for areas in code with generic enum 
> cases. The compiler could help with the change by finding the associated 
> generic and updating the case with the new syntax.
> 
>  
> Alternatives
>  considered
> 
> An alternative would be to extend the associatedtype keyword to the enum type.
> 
> enum Foo {
> associatedtype T = Hashable
> case bar(obj: T)
> }
> 
> Copy of proposal can be found here Swift proposal on github 
> 
> 
> -- 
> Joshua Alvarado
> alvaradojosh...@gmail.com 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Adrian Zubarev via swift-evolution
“Out of scope for Swift 4” means that there is no time for it now and the 
community should focus on features and issues yet to be solved in Swift 4. In 
other words it means that you should defer the proposal at least until Swift 4 
is released.



-- 
Adrian Zubarev
Sent with Airmail

Am 24. April 2017 um 21:57:13, Joshua Alvarado via swift-evolution 
(swift-evolution@swift.org) schrieb:

When would be a good time to resubmit this proposal for discussion? Or can I 
still proceed with the review and it possibly gets deferred but at least be put 
in the pipeline (if deferred)?

On Mon, Apr 24, 2017 at 9:07 AM, Douglas Gregor  wrote:

On Apr 24, 2017, at 7:23 AM, T.J. Usiyan via swift-evolution 
 wrote:

/me Pushes implementation detail related concerns out of head

+1


I want this feature but I seriously doubt that it is feasible at the moment. 
There are so many 'more pressing' features that, even if this were accepted 
now, it wouldn't be implemented it in time for Swift 4.

Out of scope for Swift 4, certainly. It may not look like it, but this is a 
fairly large feature. I suggest reading up on generalized algebraic data types 
(GADTs), which is the more programming-language-theoretical name for what 
you’re describing here.

- Doug


That said, I would love to be incorrect. 

On Mon, Apr 24, 2017 at 9:57 AM, Joshua Alvarado via swift-evolution 
 wrote:
Here is my pitch on adding generics to enum cases and not to the enum type 
itself. Let me know if you have an improvements or modifications lets open it 
to discussion thank you swiftys! :)
Enum with generic cases
Proposal: SE-
Authors: Joshua Alvarado
Review Manager: TBD
Status: PITCH
During the review process, add the following fields as needed:

Decision Notes: Rationale, Additional Commentary
Bugs: SR-, SR-
Previous Revision: 1
Previous Proposal: SE-
Introduction

This proposal adds a change to the enumeration type that allows an enum case to 
cast a generic on its associated value.

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

Enums currently support generics, but they are added onto the type itself. This 
can cause adverse syntax when implementing generics for associated values to be 
stored along each case. The enum case holds the associated value (not the enum 
type itself) so should create its own value constraints.

Proposed solution

The generic is to be casted on the case of the enum and not on the enum itself.

Detailed design

Current implementation:

// enum with two generic types
enum Foo {
case bar(obj: T)
case baz(obj: U)
}

// U is to be casted but it is not even used
let foo: Foo = .bar(obj: "hash")

// Creating an optional enum, the generics have to be casted without a value set
// The casting is really not needed as the values should be casted not the enum
var foo1: Foo?

// Collections don’t look great either
var foos = [Foo]()
foos.append(.bar(obj:"hash"))
Proposed solution

enum Foo {
case bar(obj: T)
case baz(obj: U)
}

// generic type inferred on T
var foo: Foo = .bar(obj: "hash")  

// doesn’t need to cast the generic on the optional enum
// the associated value will hold the cast
var foo1: Foo?  

// This also gives better syntax with collections of enums with associated types
var foos = [Foo]()
foos.append(.bar(obj: "hey")
Source compatibility

This may cause subtle breaking changes for areas in code with generic enum 
cases. The compiler could help with the change by finding the associated 
generic and updating the case with the new syntax.

Alternatives considered

An alternative would be to extend the associatedtype keyword to the enum type.

enum Foo {
associatedtype T = Hashable
case bar(obj: T)
}

Copy of proposal can be found here Swift proposal on github

--
Joshua Alvarado
alvaradojosh...@gmail.com

___
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




--
Joshua Alvarado
alvaradojosh...@gmail.com
___
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] [Pitch] Enum with generic cases

2017-04-24 Thread Joshua Alvarado via swift-evolution
When would be a good time to resubmit this proposal for discussion? Or can
I still proceed with the review and it possibly gets deferred but at least
be put in the pipeline (if deferred)?

On Mon, Apr 24, 2017 at 9:07 AM, Douglas Gregor  wrote:

>
> On Apr 24, 2017, at 7:23 AM, T.J. Usiyan via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> /me Pushes implementation detail related concerns out of head
>
> +1
>
>
> I want this feature but I seriously doubt that it is feasible at the
> moment. There are so many 'more pressing' features that, even if this were
> accepted now, it wouldn't be implemented it in time for Swift 4.
>
>
> Out of scope for Swift 4, certainly. It may not look like it, but this is
> a fairly large feature. I suggest reading up on generalized algebraic
> data types  
> (GADTs),
> which is the more programming-language-theoretical name for what you’re
> describing here.
>
> - Doug
>
>
> That said, I would love to be incorrect.
>
> On Mon, Apr 24, 2017 at 9:57 AM, Joshua Alvarado via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Here is my pitch on adding generics to enum cases and not to the enum
>> type itself. Let me know if you have an improvements or modifications lets
>> open it to discussion thank you swiftys! :)Enum with generic cases
>>
>>- Proposal: SE-
>>
>> 
>>- Authors: Joshua Alvarado 
>>- Review Manager: TBD
>>- Status: PITCH
>>
>> *During the review process, add the following fields as needed:*
>>
>>- Decision Notes: Rationale
>>, Additional
>>Commentary 
>>- Bugs: SR- , SR-
>>
>>- Previous Revision: 1
>>
>> 
>>- Previous Proposal: SE-
>>
>> 
>>
>>
>> 
>> Introduction
>>
>> This proposal adds a change to the enumeration type that allows an enum
>> case to cast a generic on its associated value.
>>
>> Swift-evolution thread: Discussion thread topic for that proposal
>> 
>>
>> 
>> Motivation
>>
>> Enums currently support generics, but they are added onto the type
>> itself. This can cause adverse syntax when implementing generics for
>> associated values to be stored along each case. The enum case holds the
>> associated value (not the enum type itself) so should create its own value
>> constraints.
>>
>> Proposed
>> solution
>>
>> The generic is to be casted on the case of the enum and not on the enum
>> itself.
>>
>> Detailed
>> design
>>
>> Current implementation:
>>
>> // enum with two generic typesenum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> }
>> // U is to be casted but it is not even usedlet foo: Foo = 
>> .bar(obj: "hash")
>> // Creating an optional enum, the generics have to be casted without a value 
>> set// The casting is really not needed as the values should be casted not 
>> the enumvar foo1: Foo?
>> // Collections don’t look great eithervar foos = [Foo]()
>> foos.append(.bar(obj:"hash"))
>>
>> Proposed solution
>>
>> enum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> }
>> // generic type inferred on Tvar foo: Foo = .bar(obj: "hash")
>> // doesn’t need to cast the generic on the optional enum// the associated 
>> value will hold the castvar foo1: Foo?
>> // This also gives better syntax with collections of enums with associated 
>> typesvar foos = [Foo]()
>> foos.append(.bar(obj: "hey")
>>
>>
>> Source
>> compatibility
>>
>> This may cause subtle breaking changes for areas in code with generic
>> enum cases. The compiler could help with the change by finding the
>> associated generic and updating the case with the new syntax.
>>
>> Alternatives
>> considered
>>
>> An alternative would be to extend the associatedtype keyword to the enum
>> type.
>>
>> enum Foo {
>> associatedtype T = Hashable
>> case bar(obj: T)
>> }
>>
>>
>> Copy of proposal can be found here Swift proposal on github
>> 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Jaden Geller via swift-evolution
I think the pattern match would have to introduce a new generic type variable 
within the match scope. Definitely not a simple feature, but GADTs would be so 
cool!

> On Apr 24, 2017, at 7:57 AM, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> This is somehow similar to 
> https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generic-constants.
> 
> Question, will pattern matching still work fine with that? I kinda fear that 
> this won’t work in a different scopes, but feel free to prove me being wrong.
> 
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> 
> struct Test {
>  
> var foo: Foo = .bar(obj: "swift")
>  
> func test() {
>  
> switch self.foo {
> case /* Check for `bar` and String */: …
> case /* How to pattern match against `baz`? What is `U`? */: …
>  
> // Do we need `default` everytime?
> }
> }
> }
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 24. April 2017 um 15:57:33, Joshua Alvarado via swift-evolution 
> (swift-evolution@swift.org) schrieb:
> 
>> Here is my pitch on adding generics to enum cases and not to the enum type 
>> itself. Let me know if you have an improvements or modifications lets open 
>> it to discussion thank you swiftys! :)
>> Enum with generic cases
>> Proposal: SE-
>> Authors: Joshua Alvarado
>> Review Manager: TBD
>> Status: PITCH
>> During the review process, add the following fields as needed:
>> 
>> Decision Notes: Rationale, Additional Commentary
>> Bugs: SR-, SR-
>> Previous Revision: 1
>> Previous Proposal: SE-
>> Introduction
>> 
>> This proposal adds a change to the enumeration type that allows an enum case 
>> to cast a generic on its associated value.
>> 
>> Swift-evolution thread: Discussion thread topic for that proposal
>> 
>> Motivation
>> 
>> Enums currently support generics, but they are added onto the type itself. 
>> This can cause adverse syntax when implementing generics for associated 
>> values to be stored along each case. The enum case holds the associated 
>> value (not the enum type itself) so should create its own value constraints.
>> 
>> Proposed solution
>> 
>> The generic is to be casted on the case of the enum and not on the enum 
>> itself.
>> 
>> Detailed design
>> 
>> Current implementation:
>> 
>> // enum with two generic types
>> enum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> }
>> 
>> // U is to be casted but it is not even used
>> let foo: Foo = .bar(obj: "hash")
>> 
>> // Creating an optional enum, the generics have to be casted without a value 
>> set
>> // The casting is really not needed as the values should be casted not the 
>> enum
>> var foo1: Foo?
>> 
>> // Collections don’t look great either
>> var foos = [Foo]()
>> foos.append(.bar(obj:"hash"))
>> Proposed solution
>> 
>> enum Foo {
>> case bar(obj: T)
>> case baz(obj: U)
>> }
>> 
>> // generic type inferred on T
>> var foo: Foo = .bar(obj: "hash")  
>> 
>> // doesn’t need to cast the generic on the optional enum
>> // the associated value will hold the cast
>> var foo1: Foo?  
>> 
>> // This also gives better syntax with collections of enums with associated 
>> types
>> var foos = [Foo]()
>> foos.append(.bar(obj: "hey")
>> Source compatibility
>> 
>> This may cause subtle breaking changes for areas in code with generic enum 
>> cases. The compiler could help with the change by finding the associated 
>> generic and updating the case with the new syntax.
>> 
>> Alternatives considered
>> 
>> An alternative would be to extend the associatedtype keyword to the enum 
>> type.
>> 
>> enum Foo {
>> associatedtype T = Hashable
>> case bar(obj: T)
>> }
>> 
>> Copy of proposal can be found here Swift proposal on github
>> 
>> --
>> Joshua Alvarado
>> alvaradojosh...@gmail.com
>> ___
>> 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Douglas Gregor via swift-evolution

> On Apr 24, 2017, at 7:23 AM, T.J. Usiyan via swift-evolution 
>  wrote:
> 
> /me Pushes implementation detail related concerns out of head
> 
> +1
> 
> 
> I want this feature but I seriously doubt that it is feasible at the moment. 
> There are so many 'more pressing' features that, even if this were accepted 
> now, it wouldn't be implemented it in time for Swift 4.

Out of scope for Swift 4, certainly. It may not look like it, but this is a 
fairly large feature. I suggest reading up on generalized algebraic data types 
 (GADTs), which 
is the more programming-language-theoretical name for what you’re describing 
here.

- Doug

> 
> That said, I would love to be incorrect. 
> 
> On Mon, Apr 24, 2017 at 9:57 AM, Joshua Alvarado via swift-evolution 
> > wrote:
> Here is my pitch on adding generics to enum cases and not to the enum type 
> itself. Let me know if you have an improvements or modifications lets open it 
> to discussion thank you swiftys! :)
> 
> Enum with generic cases
> 
> Proposal: SE- 
> 
> Authors: Joshua Alvarado 
> Review Manager: TBD
> Status: PITCH
> During the review process, add the following fields as needed:
> 
> Decision Notes: Rationale 
> , Additional Commentary 
> 
> Bugs: SR- , SR- 
> 
> Previous Revision: 1 
> 
> Previous Proposal: SE- 
> 
>  
> Introduction
> 
> This proposal adds a change to the enumeration type that allows an enum case 
> to cast a generic on its associated value.
> 
> Swift-evolution thread: Discussion thread topic for that proposal 
> 
>  
> Motivation
> 
> Enums currently support generics, but they are added onto the type itself. 
> This can cause adverse syntax when implementing generics for associated 
> values to be stored along each case. The enum case holds the associated value 
> (not the enum type itself) so should create its own value constraints.
> 
>  
> Proposed
>  solution
> 
> The generic is to be casted on the case of the enum and not on the enum 
> itself.
> 
>  
> Detailed
>  design
> 
> Current implementation:
> 
> // enum with two generic types
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> 
> // U is to be casted but it is not even used
> let foo: Foo = .bar(obj: "hash")
> 
> // Creating an optional enum, the generics have to be casted without a value 
> set
> // The casting is really not needed as the values should be casted not the 
> enum
> var foo1: Foo?
> 
> // Collections don’t look great either
> var foos = [Foo]()
> foos.append(.bar(obj:"hash"))
> Proposed solution
> 
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> 
> // generic type inferred on T
> var foo: Foo = .bar(obj: "hash") 
> 
> // doesn’t need to cast the generic on the optional enum
> // the associated value will hold the cast
> var foo1: Foo? 
> 
> // This also gives better syntax with collections of enums with associated 
> types
> var foos = [Foo]()
> foos.append(.bar(obj: "hey")
>  
> Source
>  compatibility
> 
> This may cause subtle breaking changes for areas in code with generic enum 
> cases. The compiler could help with the change by finding the associated 
> generic and updating the case with the new syntax.
> 
>  
> Alternatives
>  considered
> 
> An alternative would be to extend the associatedtype keyword to the enum type.
> 
> enum Foo {
> associatedtype T = Hashable
> case bar(obj: T)
> }
> 
> Copy of proposal can be found here Swift proposal on github 
> 
> 
> -- 
> Joshua Alvarado
> alvaradojosh...@gmail.com 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> 

Re: [swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Adrian Zubarev via swift-evolution
This is somehow similar to 
https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generic-constants.

Question, will pattern matching still work fine with that? I kinda fear that 
this won’t work in a different scopes, but feel free to prove me being wrong.

enum Foo {
case bar(obj: T)
case baz(obj: U)
}

struct Test {
 
var foo: Foo = .bar(obj: "swift")
 
func test() {
 
switch self.foo {
case /* Check for `bar` and String */: …
case /* How to pattern match against `baz`? What is `U`? */: …
 
// Do we need `default` everytime?
}
}
}


-- 
Adrian Zubarev
Sent with Airmail

Am 24. April 2017 um 15:57:33, Joshua Alvarado via swift-evolution 
(swift-evolution@swift.org) schrieb:

Here is my pitch on adding generics to enum cases and not to the enum type 
itself. Let me know if you have an improvements or modifications lets open it 
to discussion thank you swiftys! :)
Enum with generic cases
Proposal: SE-
Authors: Joshua Alvarado
Review Manager: TBD
Status: PITCH
During the review process, add the following fields as needed:

Decision Notes: Rationale, Additional Commentary
Bugs: SR-, SR-
Previous Revision: 1
Previous Proposal: SE-
Introduction

This proposal adds a change to the enumeration type that allows an enum case to 
cast a generic on its associated value.

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

Enums currently support generics, but they are added onto the type itself. This 
can cause adverse syntax when implementing generics for associated values to be 
stored along each case. The enum case holds the associated value (not the enum 
type itself) so should create its own value constraints.

Proposed solution

The generic is to be casted on the case of the enum and not on the enum itself.

Detailed design

Current implementation:

// enum with two generic types
enum Foo {
case bar(obj: T)
case baz(obj: U)
}

// U is to be casted but it is not even used
let foo: Foo = .bar(obj: "hash")

// Creating an optional enum, the generics have to be casted without a value set
// The casting is really not needed as the values should be casted not the enum
var foo1: Foo?

// Collections don’t look great either
var foos = [Foo]()
foos.append(.bar(obj:"hash"))
Proposed solution

enum Foo {
case bar(obj: T)
case baz(obj: U)
}

// generic type inferred on T
var foo: Foo = .bar(obj: "hash")  

// doesn’t need to cast the generic on the optional enum
// the associated value will hold the cast
var foo1: Foo?  

// This also gives better syntax with collections of enums with associated types
var foos = [Foo]()
foos.append(.bar(obj: "hey")
Source compatibility

This may cause subtle breaking changes for areas in code with generic enum 
cases. The compiler could help with the change by finding the associated 
generic and updating the case with the new syntax.

Alternatives considered

An alternative would be to extend the associatedtype keyword to the enum type.

enum Foo {
associatedtype T = Hashable
case bar(obj: T)
}

Copy of proposal can be found here Swift proposal on github

--
Joshua Alvarado
alvaradojosh...@gmail.com
___
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] [Pitch] Enum with generic cases

2017-04-24 Thread T.J. Usiyan via swift-evolution
/me Pushes implementation detail related concerns out of head

+1


I want this feature but I seriously doubt that it is feasible at the
moment. There are so many 'more pressing' features that, even if this were
accepted now, it wouldn't be implemented it in time for Swift 4.

That said, I would love to be incorrect.

On Mon, Apr 24, 2017 at 9:57 AM, Joshua Alvarado via swift-evolution <
swift-evolution@swift.org> wrote:

> Here is my pitch on adding generics to enum cases and not to the enum type
> itself. Let me know if you have an improvements or modifications lets open
> it to discussion thank you swiftys! :)Enum with generic cases
>
>- Proposal: SE-
>
> 
>- Authors: Joshua Alvarado 
>- Review Manager: TBD
>- Status: PITCH
>
> *During the review process, add the following fields as needed:*
>
>- Decision Notes: Rationale
>, Additional
>Commentary 
>- Bugs: SR- , SR-
>
>- Previous Revision: 1
>
> 
>- Previous Proposal: SE-
>
> 
>
>
> 
> Introduction
>
> This proposal adds a change to the enumeration type that allows an enum
> case to cast a generic on its associated value.
>
> Swift-evolution thread: Discussion thread topic for that proposal
> 
> 
> Motivation
>
> Enums currently support generics, but they are added onto the type itself.
> This can cause adverse syntax when implementing generics for associated
> values to be stored along each case. The enum case holds the associated
> value (not the enum type itself) so should create its own value constraints.
>
> Proposed
> solution
>
> The generic is to be casted on the case of the enum and not on the enum
> itself.
>
> Detailed
> design
>
> Current implementation:
>
> // enum with two generic typesenum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> // U is to be casted but it is not even usedlet foo: Foo = 
> .bar(obj: "hash")
> // Creating an optional enum, the generics have to be casted without a value 
> set// The casting is really not needed as the values should be casted not the 
> enumvar foo1: Foo?
> // Collections don’t look great eithervar foos = [Foo]()
> foos.append(.bar(obj:"hash"))
>
> Proposed solution
>
> enum Foo {
> case bar(obj: T)
> case baz(obj: U)
> }
> // generic type inferred on Tvar foo: Foo = .bar(obj: "hash")
> // doesn’t need to cast the generic on the optional enum// the associated 
> value will hold the castvar foo1: Foo?
> // This also gives better syntax with collections of enums with associated 
> typesvar foos = [Foo]()
> foos.append(.bar(obj: "hey")
>
>
> Source
> compatibility
>
> This may cause subtle breaking changes for areas in code with generic enum
> cases. The compiler could help with the change by finding the associated
> generic and updating the case with the new syntax.
>
> Alternatives
> considered
>
> An alternative would be to extend the associatedtype keyword to the enum
> type.
>
> enum Foo {
> associatedtype T = Hashable
> case bar(obj: T)
> }
>
>
> Copy of proposal can be found here Swift proposal on github
> 
>
> --
> Joshua Alvarado
> alvaradojosh...@gmail.com
>
> ___
> 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


[swift-evolution] [Pitch] Enum with generic cases

2017-04-24 Thread Joshua Alvarado via swift-evolution
Here is my pitch on adding generics to enum cases and not to the enum type
itself. Let me know if you have an improvements or modifications lets open
it to discussion thank you swiftys! :)Enum with generic cases

   - Proposal: SE-
   

   - Authors: Joshua Alvarado 
   - Review Manager: TBD
   - Status: PITCH

*During the review process, add the following fields as needed:*

   - Decision Notes: Rationale
   , Additional
   Commentary 
   - Bugs: SR- , SR-
   
   - Previous Revision: 1
   

   - Previous Proposal: SE-
   



Introduction

This proposal adds a change to the enumeration type that allows an enum
case to cast a generic on its associated value.

Swift-evolution thread: Discussion thread topic for that proposal


Motivation

Enums currently support generics, but they are added onto the type itself.
This can cause adverse syntax when implementing generics for associated
values to be stored along each case. The enum case holds the associated
value (not the enum type itself) so should create its own value constraints.
Proposed
solution

The generic is to be casted on the case of the enum and not on the enum
itself.
Detailed
design

Current implementation:

// enum with two generic typesenum Foo {
case bar(obj: T)
case baz(obj: U)
}
// U is to be casted but it is not even usedlet foo: Foo = .bar(obj: "hash")
// Creating an optional enum, the generics have to be casted without a
value set// The casting is really not needed as the values should be
casted not the enumvar foo1: Foo?
// Collections don’t look great eithervar foos = [Foo]()
foos.append(.bar(obj:"hash"))

Proposed solution

enum Foo {
case bar(obj: T)
case baz(obj: U)
}
// generic type inferred on Tvar foo: Foo = .bar(obj: "hash")
// doesn’t need to cast the generic on the optional enum// the
associated value will hold the castvar foo1: Foo?
// This also gives better syntax with collections of enums with
associated typesvar foos = [Foo]()
foos.append(.bar(obj: "hey")

Source
compatibility

This may cause subtle breaking changes for areas in code with generic enum
cases. The compiler could help with the change by finding the associated
generic and updating the case with the new syntax.
Alternatives
considered

An alternative would be to extend the associatedtype keyword to the enum
type.

enum Foo {
associatedtype T = Hashable
case bar(obj: T)
}


Copy of proposal can be found here Swift proposal on github


-- 
Joshua Alvarado
alvaradojosh...@gmail.com
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution