> On Apr 24, 2017, at 1:15 PM, Kevin Nattinger via swift-evolution 
> <[email protected]> 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<T, U> {
>     case thingOne(T)
>     case thingTwo(U)
> }
> 
> // How do I require thingOne<String> or thingTwo<Int>?
> func handle(thing: Thing<String, Int>) {
>     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>(T)
>     case thingTwo<T>(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<T>(let s):
```
You could use `s` like you could use `x` in `func <T>(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: 
FloatingPoint>(T)` were written in the original enum definition, you could do 
anything with `s` that you could do with a `FloatingPoint`.

>     case thingTwo<Int>(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<T>(let i):
```
When we do come back to this proposal, it might be reasonable to leave these 
sorts of specializations (e.g. `case thingTwo<Int>`) 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<T> {
    case value(T) -> Expr<T>
    case plus(Expr<Int>, Expr<Int>) -> Expr<Int>
    case and(Expr<Bool>, Expr<Bool>) -> Expr<Bool>
    case equals(Expr<T>, Expr<T>) -> Expr<T> 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 
>> <[email protected] <mailto:[email protected]>> 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-NNNN 
>> <https://github.com/lostatseajoshua/swift-evolution/blob/master/NNNN-enum-generic-cases.md>
>> Authors: Joshua Alvarado <https://github.com/alvaradojoshua0>
>> Review Manager: TBD
>> Status: PITCH
>> During the review process, add the following fields as needed:
>> 
>> Decision Notes: Rationale 
>> <https://lists.swift.org/pipermail/swift-evolution/>, Additional Commentary 
>> <https://lists.swift.org/pipermail/swift-evolution/>
>> Bugs: SR-NNNN <https://bugs.swift.org/browse/SR-NNNN>, SR-MMMM 
>> <https://bugs.swift.org/browse/SR-MMMM>
>> Previous Revision: 1 
>> <https://github.com/apple/swift-evolution/blob/...commit-ID.../proposals/NNNN-filename.md>
>> Previous Proposal: SE-XXXX 
>> <https://github.com/lostatseajoshua/swift-evolution/blob/master/XXXX-filename.md>
>>  
>> <https://github.com/lostatseajoshua/swift-evolution/tree/master#introduction>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 
>> <https://lists.swift.org/pipermail/swift-evolution/>
>>  
>> <https://github.com/lostatseajoshua/swift-evolution/tree/master#motivation>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.
>> 
>>  
>> <https://github.com/lostatseajoshua/swift-evolution/tree/master#proposed-solution>Proposed
>>  solution
>> 
>> The generic is to be casted on the case of the enum and not on the enum 
>> itself.
>> 
>>  
>> <https://github.com/lostatseajoshua/swift-evolution/tree/master#detailed-design>Detailed
>>  design
>> 
>> Current implementation:
>> 
>> // enum with two generic types
>> enum Foo<T: Hashable, U: Collection> {
>>     case bar(obj: T)
>>     case baz(obj: U)
>> }
>> 
>> // U is to be casted but it is not even used
>> let foo: Foo<String, [String]> = .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<String, [String]>?
>> 
>> // Collections don’t look great either
>> var foos = [Foo<String, [String]>]()
>> foos.append(.bar(obj:"hash"))
>> Proposed solution
>> 
>> enum Foo {
>>     case bar<T: Hashable>(obj: T)
>>     case baz<U: Collection>(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")
>>  
>> <https://github.com/lostatseajoshua/swift-evolution/tree/master#source-compatibility>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.
>> 
>>  
>> <https://github.com/lostatseajoshua/swift-evolution/tree/master#alternatives-considered>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 
>> <https://github.com/lostatseajoshua/swift-evolution/blob/master/NNNN-enum-generic-cases.md>
>> 
>> -- 
>> Joshua Alvarado
>> [email protected] 
>> <mailto:[email protected]>_______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to