- I don't like there being a new way to return an error, in effect hiding thefact that an error was returned inside a box. Having multiple returnvalues with one of them being an error has become idiomatic, andI find this helps increase the understandability of code dramatically.
I'm neutral.
+ I like the exhaustiveness checking this enables.
[…]
_ what happens when interfaces are choices inside a box? Go valuesorthogonality and composability, so this would be a natural thingfor a developer to do.
- I don't like the implicit conversion of a type into a box that the divideBox()example does, as there could be many types that could convert and itis not clear how the reader would or could know which conversion happened.It might be clearer to have names for the fields instead of just types, like a struct. Then theycould be assigned to directly. This would also help with serializationand deserialization of a box to disk or network.
- I don't like there being a new way to return an error, in effect hiding thefact that an error was returned inside a box. Having multiple returnvalues with one of them being an error has become idiomatic, andI find this helps increase the understandability of code dramatically.open questions:
_ is there some way to use boxes to support chaining when referringdeep into a tree of boxes?; so if I would normally say a.b.c.d.someMethod() butit turns out c is a box with a nil pointer (option type), then are theboxes type-checked for compatibility with chaining, and can theerror propagate up...
On Monday, September 1, 2025 at 6:50:49 PM UTC+1 Cliff wrote:Hi Gophers!
I'm trying to find the right place for this work. I spent a couple of weeks looking at early proposals and dev-team reactions to Discriminated Unions and Enums as well as feedback from surveys and open/closed proposals.
I developed box as a fundamental/orthogonal type in the compiler based on that research and I thought maybe it would serve as a discussion point - since it's an implementation that can actually be experimented with.
https://github.com/CliffsBits/discriminated_unions_and_enums_for_go
I don't think it will break any existing codebases.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/5b523201-28ed-4332-a5f9-aa9fba6ed65bn%40googlegroups.com.
It seems most likely (based on statements by the Go team) that we would not want to add a new concept that has this much semantic overlap with `interface{ a | b | c }`. But if we did that, the result would lack most of the power people want from it.
From an implementation, language theory, and sanity point of view: putting non-concrete types in a sum type won't work. If the design principles of go demand interfaces in sum types, they will never be workable.
The one 'escape hatch' for this I could see is using bounded interfaces where you limit the concrete types that can have that interface and then use those.
type example interface (typea | typeb) {
area() float64
perim() float64
}
You could use an interface like that in a sum type because it is explicitly bounded, but I think it's an ugly concept that is only necessary if you want to wedge an open-set behavioral contract concept into a closed set identity concept. A concept and syntax similar to this explanation (in support of generics) https://go.dev/blog/intro-generics would be necessary.
it is my opinion that sum types are low-hanging fruit that demand no change if implemented without interfaces. They remain as complicated and disruptive as the team has maintained if you do. There is huge value in a small language and using extension budget for a feature like this this is a social/value judgement that has technical impacts.
tldr; Sum types are trivial if you don't allow behavioral contracts or anonymous types in. Sum types are doable if you allow type restrictions on interfaces. Sum types are not doable without a) compromise or b) change.
Thanks for looking y'all - seriously - this was a design exercise for me - and it helped me understand the go-team's perspective.On Tuesday, September 2, 2025 at 5:04:36 AM UTC-4 Axel Wagner wrote:I should proof-read *before* hitting send:On Tue, 2 Sept 2025 at 11:00, Axel Wagner <axel.wa...@googlemail.com> wrote:It seems most likely (based on statements by the Go team) that we would not want to add a new concept that has this much semantic overlap with `interface{ a | b | c }`. But if we did that, the result would lack most of the power people want from it.To clarify: by "if we did that" I mean "reuse `interface{ a | b | c }`", not "add a new concept".
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/f9d02f5d-0fd2-41ef-8882-89aa49cf602an%40googlegroups.com.
type RW union {
io.Reader
io.Writer
}
mean? Or is it disallowed?
(That would be pretty unfortunate.)
What happens if you have
var r io.Reader = os.Stdin // an *os.File
var rw RW = r <- io.Reader //this disambiguation is actually not necessary - if you placed it as an io.Reader it should come out as an io.Reader - but if the os.Stdin had been placed 'raw' it would have needed a disambiguation tag. I'm not suggesting syntax (as, inShapeOf... a bunch of syntax is possible). Basically - it's manually setting the tag on the discriminated union so there is no ambiguity on retrieval.
I haven't written disambiguation syntax - I'd be happy to revisit the project if someone wants a 'complete' tool to play with - but with that as an option - I consider simple sum-types solved. The compiler source-code already has a really solid example that was introduced for generics. I think the easiest case forward would be to no longer call {type1|type2} an interface for generics - find a new word - and add disambiguation logic on insert for the classic Russ Cox case, or use 'box' as a keyword because it's neat.
(Apologies - I don't know how to quote properly)
Regarding https://github.com/golang/go/issues/54685 - sigma types. They're more complex and powerful - they could work if that's what you guys want. I prefer simple (I think the box concept is simple).