Coordinates might seem like ordinary properties at first glance, but they're most often NaryRelations; for example, state code standards relate three things: a country, a two-letter string, and a state. A CurriedFunction allows us to use a special kind of property, a CoordinateProperty, to relate the coordinate value to another property that relates, for example, the country to the state. The pattern generalizes to latitude, longitude, street numbers etc. hmm... age?

Consider an address like this one from the wonderful FRANK'S COMPULSIVE GUIDE TO POSTAL ADDRESSES:


In colloquial XML, the address part might look like:

  <street>123 MAIN ST NW STE 12</street>

The naive analog in RDF (in NotationThree) is

 [ :street "123 MAIN ST NW STE 12";
   :city "ANYTOWN"; :state "NY"; :zip "12345"].

But as we learned from the InterpretationProperties pattern, that's asking for trouble. Best to have separate subjects to attach the city and state names to, and use a property, say geo:inRegion to relate them:

 [ a :Address rdfs:label "123 MAIN ST NW STE 12";
   geo:inRegion [
     a :Zip; rdfs:label "12345";
     geo:inRegion [
       a :City; rdfs:label "ANYTOWN";
       geo:inRegion [
         a :State; rdfs:label "NY";

That's not bad, but it's not as good as it could be. The point of all those names and numbers is to uniquely identify the state, the city, etc. down to the mailing location: there's only one state called "NY", and there's only one street called MAIN ST in Anytown.

We might try...

:streetName a owl:InverseFunctionalProperty.
:mainStreet :streetName "MAIN".

but in fact, there are lots of main streets; one in just about every town in the USA. So that's not quite right. What we want is more like:

  :mainStreet1 geo:inRegion :anytown; :streetName "MAIN".
  :mainStreet2 geo:inRegion :anytown; :streetName "MAIN".
 => { :mainStreet1 = :mainStreet2 }.

This is where the CurriedFunction comes in; consider this utility schema for :[[CoordinateProperty]]:

util:CoordinateProperty s:subClassOf owl:InverseFunctionalProperty;
  owl:onProperty s:domain; owl:hasValue owl:InverseFunctionalProperty.

then our postal vocabulary says:

post:street a util:CoordinateProperty.
post:city a util:CoordinateProperty.
post:state a util:CoordinateProperty.
post:USA a post:Country.

To say that post:street is a util:[[CoordinateProperty]] is to say that for every street name (or number) there is a property, [ post:street ?NAME ] that relates a city to the street by that name in that city.

Then, if two parties independently describe main street using that vocabulary:

x:mainStreetP post:street "MAIN".
x:anytownP post:city "ANYTOWN".
x:nyP post:state "NY".

x:ny x:nyP post:USA.
x:anytown x:anytownP x:ny.
x:mainStreet x:mainStreetP x:anytown.


y:mainStreetP post:street "MAIN".
y:anytownP post:city "ANYTOWN".
y:nyP post:state "NY".

y:ny y:nyP post:USA.
y:anytown y:anytownP y:ny.
y:mainStreet y:mainStreetP y:anytown.

Then, by the semantics of OWL and RDFS, we have:

x:ny = y:ny.
x:anytown = y:anytown.
x:mainStreet = y:mainStreet.

Path shortcuts in NotationThree come in handy:

:mainStreet "MAIN"^post:street [
  "ANYTOWN"^post:city [
    "NY"^post:state USA ] ].

The analog for latitude and longitude is:

:lat a :CoordinateProperty.
:lon a :CoordinateProperty.
:earth a owl:Thing.

[ is :center of :paris] 49.0^:lat [ 2.5^:lon :earth].

That is: a subject of :lat relates a point to a circle of latitude, and a subject of :lon relates a circle of latitude to a spherical thing such as the earth.

hmm... I think this pattern might fit better with RoleNoun if it went the other way, i.e. using owl:[[FunctionalProperty]]. It might be more intuitive that way too. This orientation fits neatly with geo:inRegion from cyc, meanwhile.

discussion with some reviewers suggests the whole "coordinate" notion is a distraction and this should be phrased in terms of multi-column keys.

Last modified on 17 January 2005, at 16:29