> On Feb 20, 2017, at 1:04 PM, Matthew Johnson <matt...@anandabits.com> wrote:
> 
>> 
>> On Feb 20, 2017, at 2:38 PM, Joe Groff <jgr...@apple.com 
>> <mailto:jgr...@apple.com>> wrote:
>> 
>>> 
>>> On Feb 20, 2017, at 7:32 AM, Matthew Johnson via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>>> 
>>>> On Feb 20, 2017, at 12:40 AM, Niels Andriesse via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> I'd like to discuss the possibility of treating the cases of a given enum 
>>>> as if they are subtypes of that enum. This seems like a natural thing to 
>>>> do because enum cases (especially when they have associated values) 
>>>> effectively define a closed set of subtypes.
>>>> 
>>>> Doing so would allow for constructions such as the following:
>>>> 
>>>> enum Foo {
>>>>   case a(name: String)
>>>> }
>>>> 
>>>> func isA(foo: Foo) -> Bool {
>>>>   // The old way:
>>>>   if case .a = foo { return true }
>>>>   return false
>>>>   // The new way:
>>>>   return foo is .a
>>>> }
>>>> 
>>>> func printNameIfFooIsA(foo: Foo) -> Bool {
>>>>   // The old way:
>>>>   if case let .a(name) = foo {
>>>>     print(name)
>>>>   }
>>>>   // The new way (1):
>>>>   if let a = foo as? .a {
>>>>     print(a.name <http://a.name/>)
>>>>   }
>>>>   // The new way (2):
>>>>   if let name = (foo as? .a)?.name {
>>>>     print(name)
>>>>   }
>>>> }
>>>> 
>>>> Treating an enum's cases as its subtypes would make enums easier to work 
>>>> with because handling them would be syntactically the same as handling 
>>>> other types.
>>>> 
>>>> The pattern matching capabilities of enums wouldn't be affected by this 
>>>> proposal.
>>>> 
>>>> Multiple other proposals have already attempted to simplify enum handling 
>>>> (they have particularly focused on getting rid of "if case" and adding the 
>>>> ability to treat enum case tests as expressions), but none of the 
>>>> solutions presented in those proposals have worked out so far.
>>>> 
>>>> I believe that this could be the right solution to multiple enum-related 
>>>> problems that have been brought up repeatedly.
>>> 
>>> I would like to see enum cases treated as subtypes of the enum type.  This 
>>> is an interesting way to refer to the type of a case.  Unfortunately I 
>>> don’t think it will work if we accept the proposal to give cases a compound 
>>> name.  If we do that the name of this case becomes `a(name:)` which is not 
>>> a valid type name.
>> 
>> I think there are definitely places where having cases be a subtype of an 
>> enum make sense, but I don't think it makes sense for *all* cases to be 
>> subtypes. For example, with "biased" containers like Optional and Result, it 
>> makes sense for the "right" side to be a subtype and the "wrong" side to be 
>> explicitly constructed, IMO.  If the types of cases overlap, it would also 
>> be *ambiguous* which case ought to be constructed when the payload is 
>> converted to the enum type
> 
> Identical case types would definitely be a problem but I don’t think 
> overlapping case types are always a problem.  I imagine this conversion 
> working the same as any other ordinary overload resolution for ad-hoc 
> overloads.

Conversions happen at runtime too. `0 as Any as? Either<Int, Int>` wouldn't 
have any way to tell what `Either` to form if both arms of the Either were 
subtype candidates. An Either<T, U> in <T, U> context can end up being bound to 
Either<Int, Int> at runtime and interacting with runtime casts that way.

> 
>> —remember that enums are sums, not unions, and that's important for 
>> composability and uniform behavior with generics. 
> 
> I’ve always thought of enums as nominal discriminated unions.  Maybe I’m 
> using the wrong terminology.  Can you elaborate on the difference between 
> sums and unions?  When you say union are you talking about the kind of thing 
> some people have brought up in the past where any members in common are 
> automatically made available on the union type?

Sums maintain structure whereas unions collapse it. As a sum, Optional<T> 
maintains its shape even when T = Optional<U>. If it were a union, T u Nil u 
Nil would collapse to T u Nil, losing the distinction between the inner and 
outer nil and leading to problems in APIs that use the outer nil to communicate 
meaning about some outer structure, such as asking for the `first` element of a 
collection of Optionals.

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

Reply via email to