A list differs from a set in that the members of a list are in a specified order and there can be duplicate members. From a modeling perspective, this is a big difference. It is typical in many modeling languages to represent a list using a construct with two pointers: the first points to the current member of the list and the second points to a list which is the rest of the list. A typed list has further constraints to specify that members of the list must also be members of a specified class.
OWL does not have a standardized mechanism for typed lists. OWL builds on RDF which does have a list construct but an RDF list is not typed and, because of the way it is constructed, it’s use makes reasoning over a model theoretically undecidable. Because of the significant importance of lists in modeling many real-world domains, SADL provides a typed list construct defined in SadlListModel.owl, which is automatically added to the OwlModels folder of a project and automatically imported into any .sadl file (and its corresponding OWL file) that uses a SADL typed list construct. This basic construct in SadlListModel.owl is, in SADL syntax:
uri "http://sadl.org/sadllistmodel" alias sadllist.
^List is
a classdescribed
by ^first,
described by
rest
with values
of type
^List,
described by
lengthRestriction
with values
of type
int,
described by
minLengthRestriction
with values
of type
int,
described by
maxLengthRestriction
with values
of type
int.
A typed list is created in a SADL ontology by referencing the type
followed by the keyword List. (In the sadllist model
above, the caret (^) in front of List tells the editor that this
is not the SADL grammar keyword List but a user-defined concept named
List.) Note that the property ^first is an RDF property, as
indicated by the more florescent green color, so that the members of the
list can either be instances of a class or of a data type. Since first is
also a keyword in the SADL grammar it must be also preceded by a caret.
Below are the declaration of two typed list classes, the first with
members from the Person class and the second with members of
type XSD string.
TopTenStudents is a type of Person List.
TopTenFavoriteNames is a type of string List.
In a SADL model using a typed list construct, the typed list definition
creates a subclass of sadllist:List with some additional
restrictions.
· first can
only have values of the specified type, e.g., Person or string
in the above examples.
· rest
can only have values which belong to the class being defined, e.g., TopTenStudents
or TopTenFavoiteNames; the rest property value must
be of the same type as the subject.
ChildrenList is a type of Person List length 1-*.
creates a subclass of sadllist:List named ChildrenList
and whose members can only be instances of Person and which must
contain at least one element but can contain any larger number of
elements. Please do not confuse a cardinality restriction on a property
whose range is a subclass of sadllist:List with restrictions on
the length of instances of the sadlist:List subclass. To
illustrate:
ChildrenList
is a
type of
Person
List length
1-*.
children describes
Person
with values
of type
ChildrenList.
children
of Person
has at
most 1 value.
The first line in this example includes a list length restriction that
instances of the class ChildrenList should have at least one and
may have any larger number of members.
The third line in the example is a maximum cardinality restriction
indicating that an instance of Person should have at most one
value of the children property.
Note also that typed list classes do not have to have a name. They
can be used, for example, as the range of a property. The definition of
the property children above could use an unnamed typed list
class.
children describes Person with values of type Person List length 1-*.
This will
create an unnamed subclass of sadllist:List, and the rest
property will be restricted to values of the type of this unnamed subclass
of sadllist:List.
It is also possible to create instances of a SADL list class.
For example,
{John, Sue, Craig} are instances of Person.
JoesChildren is the ChildrenList [John, Sue, Craig].
creates an instance of ChildrenList with ordered members John, Sue, and Craig. Similarly, we could have created an instance of an unnamed subclass of sadllist:List.
JoesChildren is the Person List [John, Sue, Craig].
There are basically two kinds of things you can do with SADL typed lists.
The SADL grammar provides expressions for referencing members of a typed list. These expressions can be used in rules and queries and result in functions in the SADL intermediate form. If the active translator can translate these functions into built-in functions in the target rule or query language, then the reasoner/rule engine/query engine can do what the grammar instructs.
The SADL grammar constructs include the following, where l1 is a SADL typed list and el1 is an instance of the type of the list.
These SADL grammar constructs are equivalent, when using the Jena-based reasoner/translator pair, to the following SADL constructs, respectively, using the Jena-based built-in functions directly.
Note that in the above references, the caret before the index and length built-in function names is necessary because the names are also keywords in the SADL grammar.
Besides the grammar constructs and associated built-in functions above, the Jena-based default reasoner/translator pair support the following built-in functions for SADL typed lists.The third Jena built-in function which may be found useful in rules dealing with SADL typed lists. Because a list with more than one element is actually a sequence of lists, when using the various list operations discussed above or on other occasions it may be desirable to only operate on the first list in such a series. For example, given this model
l1 is the YooHooList [yh1, yh2, yh3, yh4].
and this rule
Rule PrintList: if x is a YooHooList and l is length of x then print(x, sadlListToString(x), " length = ", l).
inference will produce these results.
print:
<http://sadl.org/UsingListExpression.sadl#l1> [yh1, yh2, yh3, yh4]
length = 4
print: b6cb453b-6297-4cac-bd8d-a6ac96916364 [yh2, yh3, yh4] length = 3
print: c55e02b2-8968-4d19-8962-38f04d0fc800 [yh3, yh4] length = 2
print: afbbc8b7-0d10-47ac-82bc-845bff14c63e [yh4] length = 1
However, if the rule is modified as follows
Rule PrintList: if x is a YooHooList and isListHead(x) and l is length of x then print(x, sadlListToString(x), " length = ", l).
these results, which may be more what is intended when using the length built-in, are produced.
print: <http://sadl.org/UsingListExpression.sadl#l1> [yh1, yh2, yh3, yh4] length = 4
The fourth Jena built-in function may be useful, when the results are passed into the print built-in function, for debugging rules.
Besides having constraints on the type of members and the length of lists, SADL typed lists differ from RDF lists (rdf:List) in another important way. RDF has a special instance of rdf:List named rdf:nil, which is the empty list--a list without any members. Furthermore, every rdf:List is terminated by a triple with predicate and value rdf:rest rdf:nil. This is deemed unnecessary and undesirable in SADL typed lists, which simply terminate a list with an instance of the typed list that is not the subject of a sadllist:rest property.
However, an empty list instance of a SADL typed list class can occur. That such is necessary may be illustrated by asking what the function in the second line below should return given the definition of l3 in the first line.
l3
is the
YooHooList
[yh1].
deleteElementFromList(l3, 0)
In fact, an instance of an empty SADL typed list can even be declared in the grammar, either using a named sadllist:List subclass or an unnamed one.
ChildlessChildren1 is the Person List [].
ChildlessChildren2
is the
ChildrenList
[].
In RDF-XML syntax, the following is the declaration of a SADL typed list generated from the SADL
ChildrenList is a type of Person List length 1-*.
<owl:Class rdf:ID="ChildrenList">
<rdfs:subClassOf>
<owl:Restriction>
<owl:hasValue
rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:hasValue>
<owl:onProperty
rdf:resource="sadllistmodel#minLengthRestriction"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:allValuesFrom
rdf:resource="#ChildrenList"/>
<owl:onProperty
rdf:resource="sadllistmodel#rest"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:allValuesFrom
rdf:resource="#Person"/>
<owl:onProperty
rdf:resource="sadllistmodel#first"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf
rdf:resource="sadllistmodel#List"/>
</owl:Class>
In RDF-XML syntax, the following is the declaration of the instance of a SADL typed list generated from the SADL
JoesChildren is the ChildrenList [John, Sue, Craig].
<sadllistmodeltemplate:ChildrenList rdf:ID="JoesChildren">
<sadllistmodel:rest>
<sadllistmodeltemplate:ChildrenList>
<sadllistmodel:rest>
<sadllistmodeltemplate:ChildrenList>
<sadllistmodel:first rdf:resource="#Craig"/>
</sadllistmodeltemplate:ChildrenList>
</sadllistmodel:rest>
<sadllistmodel:first
rdf:resource="#Sue"/>
</sadllistmodeltemplate:ChildrenList>
</sadllistmodel:rest>
<sadllistmodel:first rdf:resource="#John"/>
</sadllistmodeltemplate:ChildrenList>
If the SADL typed list class is unnamed, as in this declaration of
the instance of a SADL typed list, the generated RDF-XML is slightly
different.
JoesChildren is the Person List [John, Sue, Craig].
<rdf:Description
rdf:ID="JoesChildren">
<sadllistmodel:rest rdf:parseType="Resource">
<sadllistmodel:rest
rdf:parseType="Resource">
<sadllistmodel:first>
<sadllistmodeltemplate:Person rdf:ID="Craig"/>
</sadllistmodel:first>
<rdf:type
rdf:nodeID="A1"/>
</sadllistmodel:rest>
<sadllistmodel:first>
<sadllistmodeltemplate:Person rdf:ID="Sue"/>
</sadllistmodel:first>
<rdf:type rdf:nodeID="A1"/>
</sadllistmodel:rest>
<sadllistmodel:first>
<sadllistmodeltemplate:Person
rdf:ID="John"/>
</sadllistmodel:first>
<rdf:type rdf:nodeID="A1"/>
</rdf:Description>
<owl:Class
rdf:nodeID="A1">
<rdfs:subClassOf>
<owl:Restriction>
<owl:hasValue
rdf:datatype="http://www.w3.org/2001/XMLSchema#int"
>1</owl:hasValue>
<owl:onProperty
rdf:resource="sadllistmodel#minLengthRestriction"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:allValuesFrom
rdf:nodeID="A1"/>
<owl:onProperty
rdf:resource="sadllistmodel#rest"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:allValuesFrom
rdf:resource="#Person"/>
<owl:onProperty
rdf:resource="sadllistmodel#first"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf
rdf:resource="sadllistmodel#List"/>
</owl:Class>