From W3C Wiki

RDF has explicit support for binary relations (properties) and unary relations (classes), but some relations are naturally NaryRelations; e.g. "Chicago is between New York and Los Angeles."

We could use a curried function for this. In NotationThree:

  :Chicago :betweenProperty :chicagoBetween.
  :NewYork :chicagoBetween :LosAngeles.

But this is arguably an AntiPattern because of its use of OnTheFlyProperties.

Currying might appeal more to ML programmers and the like; C/lisp programmers would probably prefer an ArgumentList, while those familiar with SQL and SmallTalk would find a RecordDescription most natural.

this seems to be an argument against this pattern, rather than part of it

This approach requires the invention of new ...Beetween properties for every geographical location. These properties have no useful semantics. yes, they do; they allow 3-ary expressions in a language with only 2-ary syntax. Someone looking for cities between New York and Chicago would not use the query

  ?city :betweenProperty :chicagoBetween.
  :NewYork :chicagoBetween :LosAngeles.

as it would presuppose the (sole) answer of Chicago. of course not (It's not just a trick of spelling -- the chicagoBetween property was invented at the time the first betweenProperty assertion was made about Chicago, and was probably re-invented by each independent party making such assertions about Chicago). This requires a looser query that leans only on the semantics of betweenProperty:

  ?city :betweenProperty ?p.
  :NewYork ?p :LosAngeles.

yes, of course. I don't see your point --DanConnolly

A 4-ary predicate example in RecordDescription shows how this can be a problem for extensibility.

Even for querying, this can lead to some unificiation challenges. For example, suppose we want to find the cities New York is to the (first) side of. Given:

  # middle                                     city1                     city2
  :Chicago :betweenProperty :chicagoBetween. :NewYork :chicagoBetween :LosAngeles.
  :Chicago :betweenProperty :chicagoBetween. :NewYork :chicagoBetween :SanFrancisco.
  :Madison :betweenProperty :madisonBetween. :NewYork :madisonBetween :LosAngeles.

The query

  ?middle :betweenProperty ?p.
  :NewYork ?p ?city2.

will give three answers with the bindings:

  # middle     city2
  :Chicago  :LosAngeles.
  :Chicago  :SanFrancisco.
  :Madison  :LosAngeles.

forcing us to learn twice that New York is to the first side of Chicago. huh? I don't follow

Perhaps this is a use case for including the SQL term DISTINCT in an RDF query language.

Here's another example which shows this technique more positively.

If we're gathering data about movies, one fact we might want to note is who played what role in what movie. This is a trinary relation between an actor, a character (or a role), and a film. If we used a RecordDescription, we might do:

[ a :Portrayal
; :of role:Hamlet
; :by actor:KennethBranagh
; :in film:Hamlet1996

This is good if you want to be able to talk about the portrayal itself, but otherwise you just end up with an explosion of resources (which, if they are blank nodes, makes certain types of reasoning very time-consuming).

In the curried style, you would do:

role:Hamlet :portrayalRelation role:asHamlet.

film:Hamlet1996 role:asHamlet actor:KennethBranagh.
film:Hamlet1990 role:asHamlet actor:MelGibson.
film:Hamlet2000 role:asHamlet actor:EthanHawke.

This is more concise and only requires one additional resource per role, rather than one per portrayal.

Using OWL Full, the schema for :portrayalRelation would look something like this:

:portrayalRelation a owl:FunctionalProperty
  ; rdfs:domain :Role
  ; rdfs:range :PortrayalProperty

:PortrayalProperty a owl:Class
  ; rdfs:subClassOf owl:FunctionalProperty
  ; rdfs:subClassOf
    [ a owl:Restriction
    ; owl:onProperty rdfs:range
    ; owl:hasValue :Actor
  ; rdfs:subClassOf
    [ a owl:Restriction
    ; owl:onProperty rdfs:domain
    ; owl:hasValue :Film

Which is basically an awkward way of saying that :portrayalRelation has the type :Role -> :Film -> :Actor (ie, its subject is a role and its object is a property whose subject is a film and whose object is an actor).

-- Dave Menendez

Generalizing relations to higher arities

The discussion of RecordDescription style demonstrates the generalization of a trinary relation to a quaternary relation and suggests that the CurriedFunction style cannot handle it gracefully. This is not necessarily true.

We'll start with a binary relation:

:sunnydale :teacher :joe.
# teacher : School -> Teacher

This is useful, but we want be more specific and say that Joe teaches math at Sunnydale.

:sunnydale :mathTeacher :joe.
# mathTeacher : School -> Teacher

:math :teacherRelation :mathTeacher.
# teacherRelation : Subject -> School -> Teacher

We would naturally define things so that `:mathTeacher` is automatically a subproperty of `:teacher`.

Next, we need to become more specific and say that Joe is the third grade math teacher at Sunnydale.

:sunnydale :g3mathTeacher :joe.
# g3mathTeacher : School -> Teacher

:math :g3teacherRelation g3mathTeacher.
# g3teacherRelation : Subject -> School -> Teacher

:grade3 :gradeTeacherRelation :g3teacherRelation.
# gradeTeacherRelation : Grade -> Subject -> School -> Teacher

Again, this would be set up so that `:g3teacherRelation` is a subproperty of `:teacherRelation` and `:g3mathTeacher` is a subproperty of `:mathTeacher`.

Because of the way the subproperties are set up, this query will work for both trinary and quaternary relations:

?SUBJECT :teacherRelation ?TR.

-- Dave Menendez

An alternative approach

I'd like to suggest an alternative way of phrasing the above in RDF.

:joe [a rdf:subject :mathTeacherAt
        rdf:predicate :ofGrade
        rdf:object :g3] :sunnydale

The reason I suggest this is that (assuming the statement I reified there is properly understood) this quad/pent is unique under the basic rules of RDF uniqueness. If I state it again, I won't be creating a new set of triples. Neither RecordDescription's nor the above have this property, as they both create anonymous nodes that cannot be made unique.

The approach may, of course, have downsides...

-- Chris Purcell

I'd've done:

:joe a :SunnydaleTeacher, :MathTeacher .

Though you can even merge these together to form SunnydaleMathTeacher, or break them apart: SunnydaleTeacher could be the intersection of SunndydaleSchoolEmployee and Teacher, likewise MathTeacher Mathematician and Teacher. You'd have to make inferences from all the subClassOf information in the ontology before you could perform any granular queries though.