# [swift-evolution] [Pre-Proposal-Discussion] Union Type - Swift 4

Maximilian Hünenberger m.huenenberger at me.com
Thu Aug 18 04:05:50 CDT 2016

```While purpose of the types are clear in this case there is not only intersection. I also want to find out the distance between different GeometryTypes and other properties like angels between two lines or a Line and a Plane but this doesn't make sense for a Point and some other GeometryType.

Therefore a GeometryType with subtypes is almost the perfect solution. I imagine the perfect solution would be to have something like a "newtype" feature which is similar to a protocol but the types which "conform" to it are known at compile time.

Best regards
Maximilian

> Am 18.08.2016 um 07:14 schrieb Thorsten Seitz <tseitz42 at icloud.com>:
>
> While I am a big fan of union types, I think an enum based solution for your problem is not too bad. Just use the enums only for the intersection results, i.e.
>
> enum Intersection1d {
>    case point(Point)
>    case line(Line)
> }
>
> Same for Intersection2d, but adding case plane(Plane) and so on for higher dimensions.
>
> This way the purpose of these types is clear which was not the case for a more general  GeometryValue.
>
> -Thorsten
>
>
>
>> Am 15.08.2016 um 16:29 schrieb Maximilian Hünenberger via swift-evolution <swift-evolution at swift.org>:
>>
>> I considered the enum approach but it is very tedious to use "space.add(.point(point))" which also doesn't add any clarity.
>> The other approach where we add the properties of a Point as associated values also has a major drawback:
>>
>> // you cannot create a point without "erasing" it's type
>> let point = GeometryValue.point(x: 4, y: 5)
>>
>> // if you already have a point instance
>>
>> If the union type feature is implemented the intersection of a Point and a Line returns (Point | Line) which is a subtype of a general GeometryValue eg. (Point | Line | Plane) and additionally cannot be checked for a Plane since it doesn't make sense.
>>
>> The problem with a protocol is that there are only a few methods in common and again in a method like intersect there is no exhaustiveness check in switches.
>>
>> Best regards
>> Maximilian
>>
>>> Am 12.08.2016 um 17:16 schrieb Sean Heber <sean at fifthace.com>:
>>>
>>> As an aside, you could use an enum instead of a protocol to avoid the problem of not having exhaustive switches:
>>>
>>> enum GeometryValue {
>>> case point(Point)
>>> case line(Line)
>>> }
>>>
>>> And perhaps (depending on circumstances) you might not even need a Point and Line struct, so you could just put those values inside the enum:
>>>
>>> enum GeometryValue {
>>> case point(x: Float, y: Float)
>>> case line(x: Float, y: Float, angle: Float)
>>> }
>>>
>>> However personally, I think using a protocol is the more Swifty approach to this problem. If I end up not having any common properties or functions that apply to that one umbrella protocol, then I consider that a signal that I’m modeling my solution incorrectly.
>>>
>>> l8r
>>> Sean
>>>
>>>
>>>> On Aug 12, 2016, at 6:24 AM, Maximilian Hünenberger via swift-evolution <swift-evolution at swift.org> wrote:
>>>>
>>>> Hi Cao,
>>>>
>>>> I would be in favor until I find another approach to this problem:
>>>>
>>>> Consider you have a geometry framework and two types: Point and Line
>>>>
>>>> An intersection between two lines can be either none, a point or a line (if both are identical).
>>>>
>>>> The return type would probably be (Point | Line)?
>>>>
>>>> I've modeled it with an empty protocol "GeometryType". However this has a major disadvantage:
>>>> If you have a general "GeometryType?" you have to cast it in a switch to the specific type.
>>>> In case of (Point| Line)? the switch statement can be checked for exhaustiveness.
>>>>
>>>> For future directions:
>>>>
>>>> There should also be a subtype relationship:
>>>>
>>>> let tu: (T | U) = T()
>>>> let tuv: (T | U | V) = tu // works
>>>>
>>>>
>>>> Overloaded functions/operators could also take Union types based on their overloads:
>>>>
>>>> func take(_ i: Int) -> String { ... }
>>>>
>>>> func take(_ s: String) -> Int? { ... }
>>>>
>>>> let value: (Int | String) = "1234"
>>>> let value2 = take(value) // returns (String | Int?)
>>>>
>>>> Best regards
>>>> Maximilian
>>>>
>>>>> Am 11.08.2016 um 03:28 schrieb Cao Jiannan via swift-evolution <swift-evolution at swift.org>:
>>>>>
>>>>> Hi all,
>>>>>
>>>>> I want to make a discussion about union type for swift 4.
>>>>> See https://github.com/frogcjn/swift-evolution/blob/master/proposals/xxxx-union-type.md
>>>>>
>>>>> Add union type grammar, represents the type which is one of other types.
>>>>>
>>>>> var stringOrURL: String | URL = "https://www.apple.com"
>>>>> Now, if we using the new union type feature, we can declare type conveniently, No other type declaration, and compiler will automatically calculate the common interface.
>>>>>
>>>>> func input(value: A | B |
>>>>> C) {
>>>>>
>>>>> print(value.commonProperty) // type checker will calculate the common interface, developer just use it out of box
>>>>>
>>>>>
>>>>> switch
>>>>> value {
>>>>>
>>>>> case let value as
>>>>> A:
>>>>>
>>>>> // value is type A
>>>>>
>>>>>
>>>>> print(value.
>>>>> propertyInA)
>>>>>
>>>>> case let value as
>>>>> B:
>>>>>
>>>>> // value is type B
>>>>>
>>>>>
>>>>> print(value.
>>>>> propertyInB)
>>>>>
>>>>> case let value as
>>>>> C:
>>>>>
>>>>> // value is type C
>>>>>
>>>>>
>>>>> print(value.
>>>>> propertyInC)
>>>>>  }
>>>>>
>>>>> // there is no default case other than A, B or C. we already declared that.
>>>>>
>>>>> }
>>>>>
>>>>> Note: A, B, C can be either class or protocol, or any other types. This leaves developer more freedom.
>>>>>
>>>>>
>>>>> Impact on existing code
>>>>>
>>>>>  • This is a new feature, developer who need declare common type will alter to this new grammar.
>>>>>  • Enum based version optional or IUO will be replaced by Union-based ones. Any optional type will automatically replaced by union type
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
```