3 ms·
The major problem with "bolting on" sum types to Go is that it is way too redundant with interfaces and the interactions get weird, because this already works:
by jerf 1y ago
The major problem with "bolting on" sum types to Go is that it is way too redundant with interfaces and the interactions get weird, because this already works:
type Color interface {
isColor()
}
type Red struct {}
func (r Red) isColor() {}
type Green struct {}
func (g Green) isColor() {}
type RGB struct {
Red byte
Green byte
Blue byte
}
func (r RGB) isColor() {}
func PrintColor(color Color, text string) {
switch c := color.(type) {
case Red:
// print in red here
case Green:
// print in green here
case RGB:
// handle the RGB
}
}
This doesn't prevent the zero value of a Color being 'nil' but it does make "a value of type Color" effectively a sum type because you can't do anything useful to it without unpacking it in a type-aware way. There is no way in Go to have a Red but act like you have an RGB, values always have their types.
(There is a common misconception among Go programmers that this doesn't seal the type because you can implement a "isColor" method on your own types in other packages, but it won't work. Try it if you want to be sure.)
One could argue they've effectively already been bolted on, all that is missing is some syntax gloss like
sum Color {
Red{}
Green{}
RGB{
Red byte
Green byte
Blue byte
}
}
that would simply unsugar to the above.
- jchw 1y agoYes, this is all true. However, this approach has more downsides than just nil and cumbersome syntax imo. It takes more memory and pointer-chasing than "proper" sum types would require, and while you can "seal" the type, there's no exhaustiveness checking.