Description
It's already discussed in 19412 that sum (discriminated union) types are nothing for GO 1.xx. However, unrelated to this is the fact that I find myself frequently writing boilerplate code for the interface type replacement of a discriminated union:
type Node interface {
Show() string
Read(string) bool
}
// here are some Node implementations
type IntNode struct {
value int64
}
func (n IntNode) Show() string {
fmt.Sprintf("%d", n.value)
}
func (n IntNode) Read(s string) bool {
if val, err := strconv.ParseInt(s, 10, 64); err != nil {
return false
} else {
n.value = val
return true
}
}
// The boilerplate code becomes worse with const types
type MathConstant uint16
const (
Pi MathConstant = iota
Euler
Catalan
)
type MathNode struct {
value MathConstant
}
func (n MathNode) Show() string {
switch n.value {
case Pi:
return "Pi"
case Euler:
return "Euler"
case Catalan:
return "Catalan"
}
return "Must never happen"
}
func (n MathNode) Read(s string) bool {
switch s {
case "Pi":
n.value = Pi
...
default:
return false
}
return true
}
And this is just a small example of how it could go.
Now to the Haskell deriving inspired proposal:
The idea here is like in Haskell to have a well-defined way to generate common implementations, i.e. Show, Read for algebraic types. This makes code reviews much easier and helps avoid making errors. Obviously, writing and reading less code is beneficial. Here, one could eliminate most of the boilerplate code with the 'deriving' syntax,
but one could still choose to implement custom versions if needed. This means it would be backward compatible to GO 1.xx versions:
type Node interface deriving (Show, Read)
// This will autogenerate functions with the following signature
// Show() string
// Read(string) bool
type IntNode struct {
value int64
} deriving (Show, Read)
type MathConstant uint16
const (
Pi MathConstant = iota
Euler
Catalan
)
type MathNode struct {
value MathConstant
} deriving (Show, Read)