Tl;Dr;
Given:
type A = { int: foo, int: bar }
type B = select foo from A
- What is the name of the typing relationship between A and B?
- What is the name of the operation of deriving type B from type A?
Long Version
When we talk of subtyping in programming we typically think of it in terms of whether a new subtype B of a type A is able to substitute for A. However, when you think of it in terms of implementation what you are actually saying is that B can do everything that A can. Typically B does more. It might implement the interface and add new fields and methods of its own. So despite 'sub' sounding like 'subset' the relationship is more like the subtype enriching the supertype. We derive the subtype from the supertype. I'm curious about deriving a new type by selecting a subset instead.
Consider two structures:
A = { int: foo, int: bar }
B = { int: foo }
The fields of B are a subset of the fields of A.
Is there a proper name for this relationship? I would say A includes B.
You could implement A by embedding an instance of B. As in:
C = { B, int: bar }
In a language like Go, C is the same as A. In other languages you need to reference B to get to foo. i.e. C.B.foo rather than C.foo
Another kind of subset relation is subranging. For instance limiting a integer to a range of 0-10.
Q = int
P = int[0..10]
P is a subset of Q as before. You can still say Q includes P. subranges are a special case of refinement types.
The main language I can think of where creating subsets is central is SQL. We could define B as:
B = select foo from A
So selection is probably a better term to use than "sub-setting"? B is not a subtype of A is it cannot be used as a substitute for A. A is a subtype of B because it can be. So B is a supertype of A. I think this misses the essential distinction that we are deriving B from A rather than the other way around. i.e. the process has a direction:
B = f(A) , where f = selection and B is a supertype of A
vs
subtype = g(supertype), where g is derivation/inheritance.
We also have intersection types which combine two types by producing the subset they have in common. SQL does this with joins. Unification in prolog has a similar effect. Selection is via intersection with a second type. You could view selecting the fields as constructing a set of selectors and which is then intersected with the original set. I'm not sure this is the correct way to look at it though. selection and intersection are not the same. An intersection ignores fields that are not common a selection operation should treat that as an error.
There is also destructuring (assignment) as in:
let x = { 10, 1 }
{y, z} = x
But this has to do with values more than types and the isomorphism between a structure and a generic tuple.
My question is:
- Is there a generally accepted name for this kind of 'selection'?
- What would you call a type system supporting this kind of relationship?
Bonus discussion questions:
Why is 'selection' not more common in general purpose programming languages as opposed to query languages? Surely they complement each other well?
Are there any interesting languages supporting this? How successful is the feature? (linq is very successful in C# for example)