Yes, the answer is "No".
I took a while to write this mail, so the descriptions matches your first setup (but I still think it is relevant).
I fear your are heading in a bad direction overall.
The problem is that I believe that a model (being
friendly or
enemy) has a lot of other properties (i.e. than
name and
kind). And I wonder where you would place these properties.
You could of course extend the
modelFact with all these additional properties. But I fear that you would soon find that that fact will have a huge number of arguments.
Furthermore, you may then look up in that fact all the time to obtain a property of a model (and even worse if you need to modify a property).
If I am right in these assumption then I will suggest that you use object to represent models.
Code: Select all
interface model
domains
modelKind = anyKind; friendlyKind; enemyKind.
property
name : string (o).
kind : modelKind (o).
...
end interface model
With this approach each model is an object and all properties of the model is available on that object.
You will also need a class and implementation for models.
I have added
anyKind to the domain, to be able to "pose the query" you have. But it is a bit tricky, because
anyKind is not actually a kind that a model can have, and I believe/fear that will in the end cause you more pain than relief.
Anyways, given that value I would define the "hierarchy" predicate:
Code: Select all
class predicates
isA_kind : (modelKind SubKind, model SuperKind).
clauses
isA_kind(Kind, Kind) :-
!.
isA_kind(friendlyKind, anyKind).
isA_kind(enemyKind, anyKind).
This will be the basis of you hierarchy handling.
Here I have assumed that friendly and enemy models have same "structure" and the friendly/enemy is just a simple property of a model.
But if there is more to it, you may need two additional interfaces (and classes):
Code: Select all
interface friendlyModel supports model
% things special to friendly models
end interface friendlyModel
interface enemyModel supports model
% things special to enemy models
end interface enemyModel
Now that we have a way to deal with each model, we also need a way to "store" all the models we have. We
could have them in a fact like you have:
Code: Select all
class facts
model_fact : (model Model).
The main query predicate would then return a model:
Code: Select all
class predicates
getModel_nd : (modelKind ModelKind) -> model Model nondeterm.
clauses
getModel_nd(ModelKind) = Model :-
model_fact(Model),
isA_kind(Model:kind, ModelKind).
However, you could also consider whether there is a natural "key" with which to efficiently retrieve a model. If for example the names of models must be unique (i.e. that two models cannot have the same name regardless of for example the model kind). In that case I would store the models in a map, mapping the name to the model.
Code: Select all
class facts
modelMap : mapM{string Name, model Model} := mapM_redBlack::new() [constant].
With this it is impossible to store two models with same name. Hames here a case sensitive, so you
can store "aModel" and "AModel", if you don't want to distinguish between different casing, you can use this instead:
Code: Select all
class facts
modelMap : mapM{string Name, model Model} :=
mapM_redBlack::newCustom(string::compareCaseNeutral) [constant].
With a map your query predicate will look like this:
Code: Select all
class predicates
getModel_nd : (modelKind ModelKind) -> model Model nondeterm.
clauses
getModel_nd(ModelKind) = Model :-
Model = modelMap:getValue_nd(),
isA_kind(Model:kind, ModelKind).
This predicate will not be more efficient than the one with facts, but retrieving a mode from its name will:
Code: Select all
class predicates
tryGetModel : (string Name) -> model Model determ.
clauses
tryGetModel(Name) = modelMap:tryGet(Name).
Finally a little remark about the extended
mydomain the additional names suggests that you want to classify anything in your program in a single hierarchy. Whether that is a good idea depends on whether these things does all have something in common and whether there are contexts in which any of these would be useful (i.e. is there any context in which a friendlyModel and a keyPosition can both make sense).