Understanding disjunction behavior
I am trying to better understand disjunction behavior.
When it comes to concept rows, is it the case that the instance variable that has the same name can be of different types in different rows?
Following query seems to suggest so.
Is it the case that in some rows
$x could be paperback entity instance variable, while in some other concept rows $x could be a name attribute instance variable?
A related question is following query seems to work
whereas this query fails.
when I remove one branch of the dis-junction, the query works.
What could I be going wrong?13 Replies
Are the error messages not helpful?
We have a preliminary check on the "category" of the variable, which is one of:
Type, Attribute, (Entity or Relation), Value.
The problem here is that $x is an entity in the first branch and an attribute in the second.
Thanks for the quick reply. I was wondering why did the check pass for the following two queries?
Ah right. I'll need the full explanation:
I think this is how the categories are assigned:
Where
<Instance> is Entity or Relation or Attribute. and <Object> is Entity or Relation
--
{ $x isa paperback; } or { $x isa name; };
Since isa only assigns Instance, this disjunction is fine.
--
{ $x isa paperback; $x has title "Classical Mythology"; } or { $x isa name; };
For this disjunction, the 1st branch thinks $x is an Object and the second thinks it's an instance. These are compatible[1]
--
{ $x isa paperback; $x has title "Classical Mythology"; } or { $x isa name; $x == "Homer"; };
In this case, the $x== "Homer" means the second branch requires $x to be AttributeOrValue as well. This is now incompatible with the first branch which requires Object
--
This is more of an implementation detail that has some unexpected behaviour than part of the TypeQL spec. We might try to fix it later, but having it made the rest of the codebase a lot simpler, so we may also clean it up a bit and document it.
[1] I wonder if we're handling this properly, since we'd usually decide $x is an object in this case.Thanks again for the quick reply.
I was wondering if this is the link that describes the variable "category" and compatibility rules?
I do not see
<Instance> or <Relation> defined as a variant for VariableCategory enum. Is a different terminology used for this?
While I try to understand this better, two additional questions arise.
1. Is it possible for us to see (via debug logs) what variable category has been assigned by the compiler to a variable?
2. Is it possible to hint to the compiler to attempt to infer a specific variable category for a variable?
To better illustrate "hinting", consider the following two queries.
As a user, the only difference to me between the two queries is that I am doing an equivalent of "restrict" (relation algebra "select") operation. That shouldn't result in types of $x to change.GitHub
typedb/ir/pattern/variable_category.rs at 3.5.5 · typedb/typedb
TypeDB: the power of programming, in your database - typedb/typedb
GitHub
typedb/ir/pattern/variable_category.rs at 3.5.5 · typedb/typedb
TypeDB: the power of programming, in your database - typedb/typedb
Yes, that is the implementation. We use 'Thing' and 'Instance' interchangeably sometimes.
Relation not being there is interesting. Blurring the distinction between Entity & Relation is the kind of relaxation that would fix the case you have (Blurring Attribute & Object)
As a user, the only difference to me between the two queries is that I am doing an equivalent of "restrict" (relation algebra "select") operation. That shouldn't result in types of $x to changeThat's fair and reason enough for us to relax it. Type-inference may now be mature enough to handle these cases on its own. The cases against it are something like: 1. It's rare / we don't expect it to be a useful case to model - How often would an attribute stand in for an Entity or Relation? 2. Would you want to allow a variable to be a type and an instance at the same time? (
{ $x sub person; } or {$x isa person; };
3. Should isa even return attributes, given we see attributes as "dependent" by default.
(Self::Thing, Self::AttributeOrValue) | (Self::AttributeOrValue, Self::Thing) => Some(Self::Attribute),
I think this is correct. The case it comes in is $x isa name; $x == "John";. It's safe to say $x cannot be a (primitive) Value anymore, so must be an Attribute.
Can you explain the case where you need this? If it's a very reasonable case, then (1) flies out the window and we might just relax this.
The eventual solution is to tie all of this together into a unified type-inference step which does category, type & optionality inference together.Does the following diagram accurately represent the variable category hierarchy?

Would I be right in my understanding if I were to say, outside of one special rule (
(Self::Thing, Self::AttributeOrValue) | (Self::AttributeOrValue, Self::Thing) => Some(Self::Attribute),), a variable would be assigned the narrowest possible category. When the assignment is not possible, it will result in an error.No, it's not a tree-like hierarchy. Value is ideally at the level of thing.
Delete edges:
[(Thing,AttributeOrValue)]
Insert edges: (Thing, Attribute) (AttributeOrValue, Attribute)
Like I said, this is an implementation convenience for us. Especially AttributeOrValue - It's illegal for the final category of a variable to be AttributeOrValue .
You would be right in this, yes.Please check if this is correct.

Is there any other variant besides
AttributeOrValue that would be considered illegal as the final category?
Thanks again for taking time to provide detailed replies. I really appreciate it!Not as of now. We might need an AttributeOrValueList when we get to lists
Happy that you're looking at the code @rajivranganath 😄 hopefully it's intelligible