Second draft: Sum Type by Struct

DanielG simpletangent at gmail.com
Fri Sep 4 16:35:11 UTC 2026


On Friday, 4 September 2026 at 02:52:51 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
> This is not an accurate statement.

But the examples you gave yourself directly contradict you. My 
issue is not with compact, one-line declaration per se. I'm 
talking about the fact that these languages are declaring **named 
values** (with *optional* type parameters) - not type unions, 
which are types-first, names-optional.

ML-style languages:
```
type Whatever = Case1 | Case2 | Case3 of int
```

That is **creating** named values Case1, Case2, Case3 - **not** 
referring to types declared elsewhere. `Whatever` is the type, 
Case1/Case2/Case3 are its only allowed values, and `int` is a 
payload / required constructor parameter for Case3 values.

*That is fundamentally, clearly not a union of types.* All the 
cases have to be named, none of them **have** to have typed 
payloads whatsoever.

The Haskell example you gave is the same: both 'NilSet' and 
'ConsSet' are named values (being created/declared at that 
point), and 'ConsSet' has a parameter/payload.

C#/Scala are ambiguous in this regard because (no doubt due to 
historical baggage) they use crufty syntax to accomplish the same.

And I actually should *not* have used C#15 as an example, because 
it *does* appear to have type unions now, via the new 'union' 
keyword:

.NET11/C#15 (preview):
```C#
public union IntOrString(int, string);
...
IntOrString a = 10;
IntOrString b = "nice";
var x = new IntOrString(101);
var y = new IntOrString("hi");
```

But prior to that, no such keyword/possibility. Here's how 
sumtypes look today:

.NET10/C#14
```C#
public abstract record Result;
public record Success(string Value) : Result;
public record Failure(string Error) : Result;
```

and Scala:

Scala3:
```scala
enum Result:
   case Success(value: String)
   case Failure(message: String)
```

Scala2:
```scala
sealed trait Result
case class Success(value: String) extends Result
case class Failure(message: String) extends Result
```

Incidentally, Scala3 *does* support Typescript-style type unions. 
But it's a feature which is orthogonal to, not a replacement for, 
standard sumtypes.

### What I am ultimately trying to say:

**I don't have any objection to the feature you're trying to 
add**, per se. Type unions would be a neat feature in some 
places. But please don't call this "sumtypes", refer to ML-style 
languages as prior art, and potentially complicate/constrain 
future evolution of Dlang in that direction.

The way ML-style languages implement this today is not a fad. 
Like your own DIP states, this feature goes wayyy back. Standard 
ML was already doing it exactly the way I'm describing above back 
in 1990, and that inspired Haskell, OCaml, Rust, etc:

```
datatype shape =
   | Point                     (* 'Point' is a value name, NOT a 
type! *)
   | Circle of real            (* same, but with parameterized 
construction *)
   | Rectangle of real * real
```

Respectfully, you seem to be so focused on the implementation, 
that you aren't seeing the forest for the trees. Use an 
ML-inspired language for a few months and you'll see that it's 
very different from what you're trying to do here. That's why I 
wanted to chime in early when I saw you finally posted the DIP, 
because I spend a lot of time in F# (and before that, Scala2), 
and found myself perplexed by what you previewed on Discord.

I **LOVE** sumtypes and use them all the time. I would love for D 
to finally get this feature natively, which has become absolutely 
indispensable for me. But to quote The Matrix: "Not like this ... 
not like this." (Needless to say, I'm not wild about 
`std.sumtype` - but it's a library implementation, so it doesn't 
preclude a far more elegant D-native implementation in the future)

**Could we perhaps instead simply call this proposed feature 
"type unions"?** I think you'd get a lot less pushback - maybe 
even zero! - from people who use other languages where sumtypes 
have enum-like semantics/ergonomics.

tl;dr:

**Traditional sumtypes**: names-first, typed payloads optional, 
enum-like semantics. Cases are NOT standalone types.

**Type unions**: types-first, names optional. Simply one of 
several possible TYPES.


More information about the dip.development mailing list