I like the direction the Go generics design draft has been heading in. There are however a few aspects that I feel could potentially be nicer so here's a design sketch/outline that attempts to address those. It maintains the spirit of the existing design, just frames it in a different way.
- Any type may be used as a constraint for a type parameter. This is analogous to how any type may be used to constrain ordinary non-type function parameters. See (4) for details.
- Type lists in interfaces are not part of this design.
- Sum types are added to the language, along the lines of Roger Peppe's proposal.
- There are three possibilities for type constraints:
- If the constraint is a sum type, a type argument satisfies the constraint if it would satisfy a constraint made from any of the sum type's constituent types. This can be applied recursively.
- If the constraint is an interface, a type argument satisfies the constraint if it implements the interface.
- If the constraint is any other type, a type argument satisfies the constraint if it is identical to the type, or has the type as its underlying type.
Some key similarities and differences compared to the current design draft are listed, with some discussion:
-
In the case where a simple interface (without a type list) is used as a constraint there is no difference.
-
The two new names "comparable" and "any" would still exist and function identically.
-
A big difference is that sum types are explicitly a part of this design. This increases the scope of the design, although may help reach a more coherent final outcome.
-
The proposed design separates sum types from interfaces, and uses a more convenient syntax than seems likely with the current design path.
-
The handling of an interface within a sum type used as a constraint is different to the handling of an interface within a type list. An interface within a type list is only satisfied when the type argument's underlying type is of that interface type (or they're identical types). An interface within a sum type is satisfied if the type argument implements the interface.
While these semantics naturally fall out of the proposed design, they also seem more useful to me. The obvious example being that it would allow one to write a generic Min function that handles the native types as well as any type that implements an interface containing a comparison function.
TODO...
This outline doesn't attempt to address any of the open questions about the sum types proposal although I don't think there's anything there that can't be resolved should this direction be deemed appealing. The main point here is to consider the general approach.
Overall I believe this direction will lead to Go with generics being more regular, and therefore less surprising.