Tim's Questions on Schemantic Web

I still need to see examples to understand exactly what you're getting at, Jonathan. I can't shake the feeling that you're making things too complicated -- or maybe I just don't understand some of what you're setting out to do. I certainly need to read the ABLP paper, which I haven't done yet.

Part of my confusion seems to center around weird "dual-use" functions, which behave differently depending on the number of arguments you give them -- so currying doesn't work anymore, you you have to implement them (I take it) using macros, and so on.

But at any rate, let me describe my own (much simpler, more brain-dead) thought about encoding sparql into scheme and vice-versa.

In my mind, there's one single function: ->, which we could call the "forward" function. Forward takes two arguments, a URI and a resource, and it can be curried normally. The value of (-> b a) is the object of a triple starting with a as the subject, and b as the predicate. I say "a triple," because if there exist more than one triple with a and b as subject and predicate, but with different objects, then one of the objects is chosen non-deterministically.

Sparql queries (at least, the select queries) seem as if they name things -- so I want to use the regular lambda to render them into scheme.

Here's a simple sparql query:

SELECT ?a WHERE { ?a <foo:x> 10. }

and here's how I would like to render it into scheme:

(lambda (a) (= ((-> foo:x) a) 10))

The query gets turned into a predicate function, which returns true when passed as arguments any tuple of resources which were returned by the query.

A slightly more complicated example:

SELECT ?a ?b WHERE { ?a <foo:y> <foo:z>. ?a <foo:y> ?b. ?b <foo:x> 10. }

and the Scheme version:

(lambda (a b)    (and (= ((-> foo:y) a) foo:z) (= ((-> foo:y) a) b)        (= ((-> foo:x) b) 10)))

Of course, the first query above is a sub-query (modulo renaming) in the second, so we could use the first scheme rendering above as a sub-expression in the rendering of the second query:

(define a10 (lambda (a) (= ((-> foo:x) a) 10)) (lambda (a b)     (and (= ((-> foo:y) a) foo:z)         (= ((-> foo:y) a) b)         (a10 b)))

What happens when there's a variable in the WHERE clause which isn't selected (i.e. named) in the SELECT head?

SELECT ?a WHERE { ?a <foo:x> ?b. ?b <foo:y> 50. }

We could render this as a let</tt>.

(lambda (a)    (let ((b ((-> foo:x) a))) (= ((-> foo:y) b) 50)))

This can also handle the FILTER clause pretty easily:

SELECT ?a WHERE { ?a <foo:x> ?b. FILTER ( ?b > 10 ) }

as:

(lambda (a)    (let ((b ((-> foo:x) a))) (> b 10)))

You can also handle blank nodes, UNION clauses (using or</tt>), etc.

Sparql queries with under-determined free variables seem a little harder. What do you do with this query (which, I think, is legal Sparql?)

SELECT ?a WHERE { ?a ?b ?c. }

This is asking, in some sense, for any triple. It feels like there's an existential in here. Maybe you could use a special lambda-like some</tt> for this --

(lambda (a)    (some (b c)       (= ((-> b) a) c)))

Or maybe you could project, somehow:

(project 0   (lambda (a b c)       (= ((-> b) a) c)))

Or something along those lines?

As for implementation, you want both directions: something for converting sparql into scheme (easy), and another for converting a scheme expression into sparql.

I don't remember -- how hard is it, to get the s-expr for a lambda? Given that, you could probably write a scheme-to-sparql compiler for simple expressions pretty easily.