Live data from Hacker News

Union types in C# 15

devblogs.microsoft.com

111–120 of 215 posts

Re: Union types in C# 15

#111
post #106

Hmm, they seem to have chosen to avoid names to the choices in the union, joining C++ variants and (sort of) TypeScript unions: unions are effectively just defined by a collection of types. Other languages have unions with named choices, where each name selects a type and the types are not necessarily all different. Rust, Haskell, Lean4, and even plain C unions are in this category (although plain C unions are not di…

The C and Rust union types are extremely sharp blades, enough so that I expect the average Rust beginner doesn't even know Rust has unions (and I assume you were thinking of Rust's enum not union)

I've seen exactly one Rust type which is actually a union, and it's a pretty good justification for the existence of this feature, but one isn't really enough. That type is MaybeUninit which is a union of a T and the empty tuple. Very, very, clever and valuable, but I didn't run into any similarly good uses outside that.

Re: Union types in C# 15

#112
post #106

Hmm, they seem to have chosen to avoid names to the choices in the union, joining C++ variants and (sort of) TypeScript unions: unions are effectively just defined by a collection of types. Other languages have unions with named choices, where each name selects a type and the types are not necessarily all different. Rust, Haskell, Lean4, and even plain C unions are in this category (although plain C unions are not di…

The C and Rust union types are extremely sharp blades, enough so that I expect the average Rust beginner doesn't even know Rust has unions (and I assume you were thinking of Rust's enum not union) I've seen exactly one Rust type which is actually a union, and it's a pretty good justification for the existence of this feature, but one isn't really enough. That type is MaybeUninit which is a union of a T and the empty…

Unions can be used as a somewhat safer (not safe by any means but safer), more flexible, and less error-prone form of transmute. Notably you can use unions to transmute between a large type and a smaller type.

That is essentially the motivation, primarily in the context of FFI where matching C's union behaviour using transmute is tricky and error-prone.

Re: Union types in C# 15

#113

Earlier quoted context omitted.

Yes, but that's just the default behavior. You can implement your own non-boxing version for performance critical applications.

Why on earth did they decide boxing by default was a sensible design decision... We have been pushing toward higher performance for years and this is a performance pitfall for unions would are often thought of as being lighter weight than inheritance hierarchies. F# just stores a field-per-case, with the optimization that cases with the same type are unified which is still type safe.

From what I've read, this is for the first implementation of unions, to reduce amount of compiler work they need to do. They have designed them in a way they can implement enhancements like this in the future. Things like non-boxing unions and tagged unions / enhanced enums are still being considered, just not for this version.

Re: Union types in C# 15

#114

I don't love OneOrMore It's trying to generalize - we might have exactly one T, fine, or a collection of T, and that's more T... except no, the collection might be zero of them, not at least one and so our type is really "OneOrMoreOrNone" and wow, that's just maybe some T.

> so our type is really "OneOrMoreOrNone"

If I understand correctly, it’s actually OneOrOneOrMoreOrNone. Because you have two different distinguishable representations of “one”.

The only reason to use this would be if you typically have exactly one, and you want to avoid the overhead of an enumeration in that typical case. In other words, AnyNumberButOftenJustOne.

Re: Union types in C# 15

#115
post #106

Hmm, they seem to have chosen to avoid names to the choices in the union, joining C++ variants and (sort of) TypeScript unions: unions are effectively just defined by a collection of types. Other languages have unions with named choices, where each name selects a type and the types are not necessarily all different. Rust, Haskell, Lean4, and even plain C unions are in this category (although plain C unions are not di…

Not sure, but I think C++ actually does allow std::variant with multiple choices using the same type. You might not be able to distinguish between them by type (using get()), but you can by position (get(), get(), ...)

Re: Union types in C# 15

#116
post #88

Earlier quoted context omitted.

Then this goes back to your question: > Is it good at the wrong thing? No, it's good at the right thing which is allowing developers to write type-safe SQL queries using C# at the application layer versus writing SQL that gets translated into C#.

I don't think you were aware of code gen SQL tools before this conversation right

What's the relevance here? Some sort of weird "Ha! Gotcha!" I'm certainly aware of code to SQL and SQL to code generators as generalized techniques, but I've not used SQL to code generators because these are not practical for most teams in the domain spaces where I operate.

Your original quote, verbatim:

    > Eg compare to strongly-typed query generators
"strongly-typed query generators" not "strongly-typed command generators" nor "strongly-typed code generators".

EF is precisely a code to structured query language (SQL) query generator and not a query to code generator.

Re: Union types in C# 15

#117
post #91

Earlier quoted context omitted.

OneOrMore is more or less an example from the functional world. i.e.: https://hackage.haskell.org/package/oneormore or scala: https://typelevel.org/cats/datatypes/nel.html it's for type purists, because sometimes you want the first element of the list but if you do that you will get T? which is stupid if you know that the list always holds an element, because now you need to have an unnecessary assertion to "fix" the…

The NonEmptyList in Cats is a product (struct/tuple) type, though; I assume the Haskell version is the same. The type shown in the blog post is a sum (union) type which can contain an empty enumerable, which contradicts the name OneOrMore. The use described for the type in the post (basically a convenience conversion funnel) is different and makes sense in its own right (though it feels like kind of a weak use case).…

Well you are right of course, I just wanted to explain what they wanted to show. Of course the type would be wrong if the second entry in itself is an empty list. I just wanted to explain the reasoning what they tried to accomplish

They could’ve done the Either type which would’ve been more correct or maybe EitherT (if the latter is even possible)

Re: Union types in C# 15

#118

Earlier quoted context omitted.

The C and Rust union types are extremely sharp blades, enough so that I expect the average Rust beginner doesn't even know Rust has unions (and I assume you were thinking of Rust's enum not union) I've seen exactly one Rust type which is actually a union, and it's a pretty good justification for the existence of this feature, but one isn't really enough. That type is MaybeUninit which is a union of a T and the empty…

Unions can be used as a somewhat safer (not safe by any means but safer), more flexible, and less error-prone form of transmute. Notably you can use unions to transmute between a large type and a smaller type. That is essentially the motivation, primarily in the context of FFI where matching C's union behaviour using transmute is tricky and error-prone.

There are rare cases where all attributes of the C union are valid at the same time. Say you have a 32-bit RGBA color value and you want to access the individual 8 bit values. You can make a union of an 32 bit int and a struct that contains 4x 8 bit integers.

Also you can manually tag them and get s.th. more like other high level languages. It will just look ugly.

Re: Union types in C# 15

#119

Earlier quoted context omitted.

Why on earth did they decide boxing by default was a sensible design decision... We have been pushing toward higher performance for years and this is a performance pitfall for unions would are often thought of as being lighter weight than inheritance hierarchies. F# just stores a field-per-case, with the optimization that cases with the same type are unified which is still type safe.

From what I've read, this is for the first implementation of unions, to reduce amount of compiler work they need to do. They have designed them in a way they can implement enhancements like this in the future. Things like non-boxing unions and tagged unions / enhanced enums are still being considered, just not for this version.

This is the general pattern of how the C# team operates, IME.

    "Never let perfect be the enemy of good"
Very much what I've seen from them over the years as they iterate and improve features and propagate it through the platform. AOT as an example; they ship the feature first and then incrementally move first party packages over to support it. Runtime `async` is another example.

Re: Union types in C# 15

#120
Sad part is, is that ad hoc unions probably won’t make it into v1. That is probably one of the only feature why I like typescript. Because I can write result types in a good way without creating thousands of sub types. It’s even more important when using Promises and not having checked exceptions.
Post reply on HN