Guile-RDF ============ Guile RDF is an implementation of the RDF format defined by the W3C for GNU Guile. RDF stands for Resource Description Framework and it is a way to represent information. RDF structures include triples (facts with a subject, a predicate and an object), graphs which are sets of triples, and datasets, which are collections of graphs. Each node in the graph represents a "thing", a concept or concrete object, and edges represent relations between them. Each node and relation is either an IRI, a blank node or an RDF literal. An RDF literal itself has a type, represented by an IRI. RDF specifications include the specification of concrete syntaxes and of operations on graphs. This library is not yet complete, but already has some basic functionalities: an internal representation of RDF datasets, some predicates and an initial parser for turtle files. Installing ---------- In order to install, your best option is to use the [Guix](https://guix.gnu.org) package manager. It can run on any existing Linux distribution, and is guaranteed to not interact with its host distribution. Installing Guix is as simple as running the [installation script](https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh). Once installed, you can run: ```bash guix install guile guile-rdf ``` Otherwise, your package manager might have guile-jsonld available. You can also build it from source, like so: ```bash git clone https://framagit.org/tyreunom/guile-rdf autoreconf -fiv ./configure make sudo make install ``` You will need guile and guile-json for it to work. Again, the best way to obtain the dependencies is to use Guix from this repository: ```bash guix environment -l guix.scm ``` `guix.scm` is a file that is provided with this repository. You can use it to setup a development environment, as shown above, or to build the package, using maybe a different source, like this: ```bash guix build --with-sources=guile-rdf=$(PWD) -f guix.scm ``` Testing ------- The tests include running the official [test suite](https://w3c.github.io/json-ld-api/tests/). It requires network access. To run it, use: ```bash make check ``` Please [report](https://framagit.org/tyreunom/guile-jsonld/issues) any failure! Documentation ------------- This section documents the RDF library. It is mostly based on the different recommendations from the W3C. ### RDF Structures The RDF Structure is defined in module `(rdf rdf)`. #### **Scheme Datatype**: `rdf-dataset` An RDF dataset is a set of graphs, with one default graph and a set of named graphs. This type has the following fields: * **default-graph**: the default graph, an RDF graph * **named-graphs**: the list of named graphs, an alist where keys are names and values are graphs. #### **Scheme Datatype**: `rdf-triple` An RDF triple is a truth assertion that a subject is linked to an object by a certain predicate. This type has the following fields: * **subject**: The subject, which can be a blank node, an IRI, a datatype or a literal * **predicate**: The predicate, which can have the same type of values * **object**: The object, which can have the same type of values Note that the recommendation restricts the possible values for predicate further (it should not be a blank node for instance), but also introduces the notion of *generalized RDF*, which corresponds to our definition of a triple. This is useful for entailment. A valid RDF triple can still be represented with this datatype. #### **Scheme Datatype**: `rdf-literal` An RDF literal is the value of a node. This type has the following fields: * **lexical-form**: The lexical form of the literal, a unicode string. * **type**: The type of the literal. This can be either an IRI or an RDF datatype (described later). * **langtag**: An optional language tag. Note that when `langtag` is defined, the type is necessarily rdf:langString. Note that the `langtag` restriction only applies semantically. Operations on RDF graphs and datasets as implemented in this library do not check that it is well-formed. Parsers and producers will fail to execute when the type is not as expected though. #### **Scheme Procedure**: blank-node? node Returns wether a node is a blank node or not. Blank node representation is internal and should not be relied upon as it might change without prior notice. Two blank nodes can be compared for equality (or unequality) with `equal?`. Other procedures are not guaranteed to work on blank nodes. #### **Scheme Procedure**: rdf-graph? graph Returns whether a scheme value is an RDF graph. This does not check the consistency or validity of the graph, but merely that it is syntactically correct. ### RDF Datatypes Datatypes are used to add semantics to literals. The `(rdf rdf)` further defines them, as well as some base datatypes. #### **Scheme Datatype**: `rdf-datatype` This type has the following fields: * **iris**: A list of IRIs that represent this type * **description**: A string describing that datatype, usually taken from documentations or recommendations * **literal?**: A procedure to check whether a string is a literal of that type * **value?**: A procedure to check whether a value is of that type * **lexical->value**: A procedure to transform a valid literal into a value value * **value->lexical**: A procedure to transform a valid value into a valid literal Note that there might be more that one valid value or literal to transform into. The last two procedures will choose one canonical representation. The documentation does not refer to `value->lexical`. It is an addition of this implementation. #### **Scheme Datatype**: `rdf-vocabulary` A vocabulary is a collection of datatypes. This implementation also equips a vocabulary with utility functions. This type has the following fields: * **datatypes**: A list of RDF datatypes * **order**: A procedure that returns whether the first datatype's value space is included in the value space of the second (i.e. whether it is smaller). * **compatible?**: A procedure that returns whether the two datatypes passed as parameters are compatible, i. e. their value space is not disjoint. Compatibility is assumed to be total (it always answers for any pair of recognized datatype in the vocabulary). One of the consistency conditions of a graph is that when a node has multiple types, they must have at least one value in common (for instance, a node can be both an integer and a decimal, because integer values are both integers and decimals, but it cannot be a boolean and an integer). The type consistency of a node is mathematically expressed as the non-emptyness of the intersection of value spaces of all the types of the node. It is assumed in this implementation that, when all the types or two-by-two compatible, that intersection is not empty. This is not true in general, but works at least of the base vocabulary included in guile-rdf. **Help wanted**: if you can come up with a better algorithm, please share! #### Available Datatypes in `(rdf rdf) * rdf:langString * rdf:XMLLiteral #### Available Datatypes in `(rdf xsd)` When you import this module with `#:prefix xsd:`, you can easily use these literals with that prefix, in the same way you would write it in a concrete RDF document. For instance, the following is a valid triple: ```scheme (make-rdf-triple "http://example.org/a" "http://example.org/prop" (make-rdf-literal "10" xsd:integer #f)) ``` Representing (in turtle syntax): ``` @prefix xsd: http://www.w3.org/2001/XMLSchema# "10"^^xsd:integer . ``` Available datatypes are: * xsd:boolean * xsd:string * xsd:decimal * xsd:integer * xsd:int ### Graph Operations The `(rdf rdf)` module also defines some graph operations. They are presented below. #### **Scheme Procedure**: `merge-graphs g1 g2` Merges two graphs. As graphs are collections of RDF triples, this is very similar to appending the two sets. However, we must ensure that we don't accidentaly merge blank node identifiers that should not be merged, as two distinct blank nodes can have the same internal representation in both graphs. #### **Scheme Procedure**: `rdf-isomorphic? g1 g2` Returns whether two graphs are the same. Two graphs can have a different representation because of order and because of differing blank node representations. For instance the following graphs (in turtle format) are isomorphic, even though their representation is different: ``` _:a1 "10"^^ ``` and ``` _:bn "10"^^ ``` However, the following is *not* isomorphic with any of the previous graphs: ``` _:a1 "010"^^ ``` Because the literal representation of `10` differs. #### **Scheme Procedure**: `recognize graph vocabulary` Transforms a graph to replace every instance of recognized IRIs in the vocabulary by an RDF datatype.