Open james-whiteside opened 8 months ago
We discussed the plays*
and owns*
keyword before. There is nothing on the modeling theory side that fundamentally obstructs introducing them. Under the hood, they could act like macros that are simply expanded into plays
and owns
declarations for all sub-interfaces (kept up-to-date when the schema changes of course). That being said, we should probably spend more time gauging interest and relevance before introducing the new *
operator.
There is a need for the replacement of a relation on an attribute. This replacement could used to accomplish high-value, broadly applicable infrastructure capabilities that require relations linking to attributes where a relation owning all attributes becomes impractical due to the sheer number of attributes,
Example use cases include:
cybersecurity markings
The aim should be to build this capability as modular extensions to the current IAM.
Instead of needing a relation owning >400 attributes, maybe the above approach would work, if we
Question
Current variance behaviour
Currently, definitions of interface implementations (i.e.
owns
andplays
statements) are covariant in the implementing type (the owner or roleplayer), and invariant in the implemented interface (the ownership or role). Consider the following example.In this case,
bird
is able to playflock:flock-member
because the implementation bybird
is covariant, butanimal
is not able to play the role because the interface itself is invariant. This is correct behaviour. If we translate the schema into natural language, we'd get the following facts.Based on these facts, the following deduction is correct by modus ponens.
However, the following deduction is incorrect by affirming the consequent.
The current behaviour of TypeQL is consistent with these rules of predicate logic. In fact, to be completely correct, interfaces would need to be contravariant rather than invariant, but that's not the point of this issue.
TypeQL's key value prop
One of TypeQL's most valuable features is its declarativity. The fact that
goose
can playflock:flock-member
because it is a subtype ofbird
without us having to separately declare it is a big value prop. If we introduce new subtypes ofbird
, then they will get this capability automatically. This is consistent with the fact "all birds can join flocks".Compare the approach of a relational database, where we'd have to explicitly declare the behaviour for every subtype. Then, if we introduce a new subtype of bird, it doesn't automatically get the capability. This is inconsistent with the fact "all birds can join flocks". The fact actually expressed by the relational database is "all geese, magpies, and herons can join flocks", so naturally the new bird subtype wouldn't gain the capability.
The key value prop of TypeQL, when compared with SQL, is that we are able to accurately express the fact "all birds can join flocks".
The gap in expressivity
Let's say we want to allow any animal to join any animal group, strange as it would be. The current approach to doing this in TypeQL would involve declaring
animal
to play every group member subtype, for instance as follows.If we were to introduce a new animal group, for instance a pride, then all animals would not automatically gain the capability to join prides. This is inconsistent with the intended behaviour, which would be represented by the fact "all animals can join all animal groups". The fact actually expressed is "all animals can join flocks, herds, and pods".
In this instace, the expressivity of TypeQL does not exceed that of SQL.
Filling the gap
While we certainly want invariant (or contravariant) interfaces, we also want to be able to have covariant interfaces. This would allow both of the following facts to be accurately expressed in TypeQL.
Currently, only the former can be accurately expressed. This has many more realistic applications, for instance allowing any person to be any kind of employee, even kinds that have not been defined yet, which is expressed as "all people can be all types of employee". The inability to express this is contrary to our key value prop.
Proposed syntax
Introduce new keyword variants
owns*
andplays*
. These would cause interface implementations to be covariant in implementing type, and covariant (or bivariant) in the implemented interface.