Live data from Hacker News

Union types in C# 15

devblogs.microsoft.com

151–160 of 215 posts

Re: Union types in C# 15

#151

Earlier quoted context omitted.

I'm 100% on board with the [] syntax. I'm not on board with adding the syntax for passing arguments to the constructor within that syntax. I agree that = [] is perfectly fine syntax. But I would definitely argue that: [with(capacity: values.Length * 2), .. is non-intuitive and unnecessary. What other language is there that has this syntax? Alternatively, is this a natural way of writing this? I wouldn't say so. My ma…

Hi there. Designer of this feature :D > is non-intuitive and unnecessary. intuitive is definitely in the eye of the beholder. When people saw: `HashSet people = [with(StringComparer.CaseInsensitiveComparer), .. group1, group2]` they found it understandable. And this was also much nicer than what they'd have to write today (which would bring them out of the nice declarative collection-expression space). Does that make…

Practically speaking, I've found that Claude never uses collection expressions, so the feature has disappeared from my code. Before AI, the feature was looked at with skepticism by my coworkers. We like writing "var" for all variable declarations. You have to write the type on the left side if you want to declare a variable with a collection expression, and we would never do that otherwise. Can't do `foreach (var x in [1, 2, 3])`. Too often, you have to make specific accommodations in your code to allow the collection expression to be valid.

Collection expressions today are more the sort of thing that a code poet or golfer can do to prettify their code than something a newbie can count on using. It's tough to explain "you can only use this when the collection type is implied in that spot" to a newbie. The value of the base feature is still unproven for me. I'm not sure I agree, without some convincing, that collection expressions made the language more coherent rather than doing https://xkcd.com/927.

Re: Union types in C# 15

#152
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…

I would love to see a page that has cross-language comparisons of how different structures work. Eg “unions: differences between langs. Enums: …” while grouping together the different design choices, as you do in this one case.

I suppose an LLM could do a pretty good job at this.

Re: Union types in C# 15

#153

Earlier quoted context omitted.

My knowledge on functional languages is limited, but as I understand it, it’s possible to formulate expressions that are basically NP problems? And hence impossible to speed up? So is it a F# issue or inherent to functional programming?

AFAIK it was a much more down-to-earth thing. The implementation of computation expressions in F# compiled down to lots of function objects that were not very GC-friendly. Or something like that. To be honest, I never looked that deeply at it :) Looking at it, the MS docs contain something about this exact topic, so maybe it's better nowadays: https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref... Sadly, I h…

F# has since gotten Functional State machines which make many computation expressions more efficient (https://github.com/fsharp/fslang-design/blob/main/FSharp-6.0...). Been there a while.

I actually think F# has received some "love" over the recent years contrary to some on this forum; that feature being an example. My view, maybe unpopular but in the age of AI maybe less so, is there is a diminishing returns to language features anyway w.r.t complexity and the use cases that new feature will actually apply for. F# in my mind and many other languages now for that matter is pretty much there or are almost there; the languages are converging. When I used F# I liked how it unified features and tried to keep things simple. Features didn't feel "tacked on" mostly with some later exceptions.

Last time I used F# a few libraries started adopting this for their CE's (e.g. IcedTasks library, etc).

Re: Union types in C# 15

#154

Earlier quoted context omitted.

Not OP but I would love to check that out

Sure, as an example: https://github.com/dotnet/csharplang/blob/main/meetings/work... Again, very rough. We go round and round on things. Loving to decompose, debate and determine how we want to tackle all these large and interesting areas :)

Nice! (Well, nice the first time I loaded the page, but GitHub appears to be rocking maybe 90% uptime today and I can’t see it anymore.)

I admit that I haven’t actually used C# in 20 years or so.

Re: Union types in C# 15

#155

Earlier quoted context omitted.

I'm 100% on board with the [] syntax. I'm not on board with adding the syntax for passing arguments to the constructor within that syntax. I agree that = [] is perfectly fine syntax. But I would definitely argue that: [with(capacity: values.Length * 2), .. is non-intuitive and unnecessary. What other language is there that has this syntax? Alternatively, is this a natural way of writing this? I wouldn't say so. My ma…

Hi there. Designer of this feature :D > is non-intuitive and unnecessary. intuitive is definitely in the eye of the beholder. When people saw: `HashSet people = [with(StringComparer.CaseInsensitiveComparer), .. group1, group2]` they found it understandable. And this was also much nicer than what they'd have to write today (which would bring them out of the nice declarative collection-expression space). Does that make…

As someone who has been coding C# since the pre-generics days, this is the first syntax change which I strongly disagree with. I pretty much love every little bit of syntactic sugar you guys have added to the language. But this? This seems objectively illogical and just straight up ugly. It blows my mind that this is making it into the language, and it makes me worry about the future of C#.

Re: Union types in C# 15

#156

Earlier quoted context omitted.

> It doesn't cover ad-hoc unions Yes and no. C# unions aren’t sealed types, that’s a separate feature. But they are strictly nominal - they must be formally declared: union Foo(Bar, Baz); Which isn’t at all the same as saying: Bar | Baz It is the same as the night and day difference between tuples and nominal records.

Hi there! One of the C# language designers here, working on unions. We're very interesting in this space. And we're referring to it as, unsurprisingly, 'anonymous unions' (since the ones we're delivering in C#15 are 'nominal' ones). An unfortunate aspect of lang design is that if you do something in one version, and not another, that people think you don't want the other (not saying you think that! but some do :)). T…

Very good to hear that!

Re: Union types in C# 15

#157

Earlier quoted context omitted.

Hi there. Designer of this feature :D > is non-intuitive and unnecessary. intuitive is definitely in the eye of the beholder. When people saw: `HashSet people = [with(StringComparer.CaseInsensitiveComparer), .. group1, group2]` they found it understandable. And this was also much nicer than what they'd have to write today (which would bring them out of the nice declarative collection-expression space). Does that make…

As someone who has been coding C# since the pre-generics days, this is the first syntax change which I strongly disagree with. I pretty much love every little bit of syntactic sugar you guys have added to the language. But this? This seems objectively illogical and just straight up ugly. It blows my mind that this is making it into the language, and it makes me worry about the future of C#.

How do you define "objectively illogical" here?

Re: Union types in C# 15

#158
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…

FYI small string optimizations are generally implemented using unions.

Re: Union types in C# 15

#159
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…

Careful not to mix unions with sum types, though. The key distinction is that the latter are disjunct sets, even if you "sum" together the same type twice, you can always tell which "way" you went.

An example that may show the difference: if you have a language with nullable types, then you basically have a language with union types like String|Null, where the Null type has a single value called `null` and String can not be null.

Now if you pass this around a function that itself may return `null`, then your type coalesces to String|Null still (you still get a nullable string, there is no doubly nullable). This is not true for Maybe/Option whatever you call types, where Some(None) (or Optional.of(Optional.empty())) is different from None only.

Rich Hickey once made a case that sort of became controversial in some FP circles, that the former can sometimes be preferred (e.g. at public API surfaces), as in for a parameter you take a non-nullable String but for returns you return a String|Null. In this case you can have an API-compatible change widening the input parameters' type, or restricting the return type - meanwhile with sum types you would have to do a refactor because Maybe String is not API compatible with String.

Re: Union types in C# 15

#160

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.

`OneOrMore ` was an example of using `union` types. You are free to call it `public union Some (T, IEnumerable )`

But now you can only call methods that are available for both T and IEnumerable, you have no way of knowing which it actually is. (You would know if it were sum types)
Post reply on HN