I disagree with you that this is non-idiomatic Go code, but that's by-the-by: no one can agree on what the idiomatic way really is, anyways.
On your solution: you're right in that you can define separate types for each of these values, then have them implement a common interface. But that ends up getting pretty weird for our codebase, as we pass the types around between a variety of packages and re-typing them so you can implement the handler code in that specific place leads to some really awkward code organisation, and I think would be a net worse.
> You also have no compiler support for detecting that you missed a case. Again, Go's m.o., so shrug.
The original article is just about getting us compiler support for catching the missing cases, in a way that we can easily change existing switch statements to support it.
It shouldn't be offensive, and it definitely didn't take any of our 'design' budget: it's very simple, and took less than an hour to put together and adopt it in the codebase.
Sounds like it's not your cup of tea, but it is a nice improvement for us :)
I was talking about a Value type being a sum type. Your widget type shouldn't be a sum type at all.
For your new widget, you define an interface and you call a method. You do get full compiler support for ensuring that the method exists because if you try to pass the new widget type in to something that defines the interface, and it does not implement the interface, it is a compile-time error.
This is absolutely unidiomatic. You pay for implementing a foreign paradigm into Go code, then you pay for that foreign paradigm not doing the task you're asking it to do very well, where the native paradigm does it smoothly and correctly. This is doubly-non-idiomatic code; it's non-idiomatic Go and it's non-idiomatic FP!
Sorry, but interfaces are not a replacement for sum types. Trying to shoehorn every situation where you might want to deal with multiple different types of things into figuring out what common interface they could implement is a pretty terrible pattern (although interfaces are great where they are actually applicable). The Go solution of using reflection on empty interfaces and type switches when the interface pattern fails instead of sum types is a hack that forces you to throw away type safety.
Go <1.18 often feels like it is an half-finished language, except there are a lot of people ready to jump down your throat about how it's actually good that it is half-finished. Real "ignorance is strength" vibes. And I'm someone who writes Go every day.
I disagree with you that this is non-idiomatic Go code, but that's by-the-by: no one can agree on what the idiomatic way really is, anyways.
On your solution: you're right in that you can define separate types for each of these values, then have them implement a common interface. But that ends up getting pretty weird for our codebase, as we pass the types around between a variety of packages and re-typing them so you can implement the handler code in that specific place leads to some really awkward code organisation, and I think would be a net worse.
I think this is your article? http://www.jerf.org/iri/post/2917
If so, you say yourself:
> You also have no compiler support for detecting that you missed a case. Again, Go's m.o., so shrug.
The original article is just about getting us compiler support for catching the missing cases, in a way that we can easily change existing switch statements to support it.
It shouldn't be offensive, and it definitely didn't take any of our 'design' budget: it's very simple, and took less than an hour to put together and adopt it in the codebase.
Sounds like it's not your cup of tea, but it is a nice improvement for us :)