> 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