First Draft: Nominal Sum Types via `enum union` and `switch` Expressions
Dejan Lekic
dejan.lekic at gmail.com
Thu Sep 24 12:40:30 UTC 2026
On Thursday, 24 September 2026 at 00:21:53 UTC, Meta wrote:
> On Wednesday, 23 September 2026 at 22:23:46 UTC, Meta wrote:
>> That can be simplified to:
>> ```d
>> enum union DynamicNumber
>> {
>> case long, float, double, error(string);
>> }
>>
>> DynamicNumber sum(DynamicNumber a, DynamicNumber b) @safe
>> {
>> enum isBare(alias V) = __traits(variantKind, V) == "bare";
>> alias NumericVariants = Filter!(isBare,
>> __traits(allVariants, DynamicNumber));
>> return switch (a)
>> {
>> case error => a,
>> static foreach (V1; NumericVariants)
>> case V1 v1 => switch (b)
>> {
>> case error => b,
>> static foreach (V2; NumericVariants)
>> case V2 v2 => DynamicNumber(v1 + v2),
>> },
>> };
>> }
>> ```
>>
>> Actually that's pretty straightforward for a fairly complex
>> case. The only thing that's needed is static foreach support
>> for generating switch arms, which is on my todo list already.
>
> And it's now implemented:
> ```d
> enum union Shape
> {
> case Circle(double);
> case Rect(double, double);
> case Point();
> }
>
> double area(Shape s)
> {
> return switch (s)
> {
> static foreach (T; __traits(allVariants, Shape))
> {
> static if (__traits(identifier, T) == "Circle")
> {
> case Circle(r) => 3.14159 * r * r,
> }
> else static if (__traits(identifier, T) == "Rect")
> {
> case Rect(w, h) => w * h,
> }
> else
> {
> // Optional trailing delimiter before right
> curly
> case Point() => 0.0
> }
> }
> };
> }
>
> Shape sh = Shape.Rect(3.0, 4.0);
> assert(area(sh) == 12.0);
> ```
Is it me or this is just terrible, and this is just a tiny
example. For anything more serious (read - real world use cases)
the amount of ugly code like the one above would be enormous...
More information about the dip.development
mailing list