In order to simplify:
A pragmatic introduction to the power of RDF for Solid

Ruben Verborgh, Ghent Universityimec

These slides are an abridged version of my Web Fundamentals course.

In order to simplify

A pragmatic introduction to
the power of RDF for Solid

Ruben Verborgh

Why do we use RDF
within Solid?

Surely there must be something easier.

I used to like math, until
the numbers were being
outnumbered by letters.

And then the letters
started having letters.

Dieter DP

💰 🍎🍏 📦

I bought a crate of apples for £20
and just sold 6 apples for £5 each.
What is my profit?

10 = 5 ⋅ 6 − 20

This solves buying a crate of apples for £20
and selling 6 apples for £5 each.

f(x) = 5 x − 20

This solves selling an arbitrary number of apples,
and even half an apple or negative apples due to loss.

f(x) = ax + b

This solves selling arbitrary numbers of anything,
and whole other kinds of problems.

Are the letters really
the difficulty here?

In order to simplify,
one must complexify,
i.e., see simple things
in the complex plane.

Gaston Julia (as quoted by Benoît Mandelbrot)

A well-designed complexity
must deliver simplicity.

What happened to good old natural numbers?

So is RDF really
the difficulty here?

People think RDF is a pain
because it is complicated.
The truth is even worse.

RDF is painfully simplistic,
but it allows you to work with real-world data
and problems
that are horribly complicated.

Dan Brickley & Libby Miller

An immense amount of Linked Data
is available on the Web for reuse.

No Linked Data set is ever complete.
We make the open-world assumption.

The Resource Description Framework is
a model for data interchange on the Web.

How many syntaxes for RDF exist?
Which one(s)?

N-Triples is a line-based syntax
supporting only a default graph.

<http://dbpedia.org/resource/Tim_Berners-Lee> <http://xmlns.com/foaf/0.1/knows> <http://dbpedia.org/resource/Ted_Nelson>.
<http://dbpedia.org/resource/Tim_Berners-Lee> <http://xmlns.com/foaf/0.1/givenName> "Tim"@en.
<http://dbpedia.org/resource/Tim_Berners-Lee> <http://dbpedia.org/ontology/birthDate> "1955-06-08"^^<http://www.w3.org/2001/XMLSchema#date>.

Turtle is a superset of N-Triples
with prefixes and abbreviations.

PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

dbr:Tim_Berners-Lee a foaf:Person;
                    foaf:knows dbr:Ted_Nelson,
                               dbr:Wendy_Hall.

N-Quads is a superset of N-Triples
with support for named graphs.

# Triples in the default graph look like N-Triples
<urn:ex:s1> <urn:ex:p1> <urn:ex:o1>.
<urn:ex:s1> <urn:ex:p2> "abc".

# Triples in named graphs have a fourth element
<urn:ex:s2> <urn:ex:p1> <urn:ex:o2> <urn:ex:GraphA>.
<urn:ex:s2> <urn:ex:p2> "xyz" <urn:ex:GraphB>.

TriG is a superset of Turtle (not N-Quads)
with support for named graphs.

# Triples in the default graph look like Turtle
dbr:Tim_Berners-Lee foaf:knows dbr:Ted_Nelson.

# Named graphs are indicated by a graph statement
<http://example.org/graphs/Fiction> {
    dbr:Clark_Kent a foaf:Person;
                     foaf:nick "Superman"@en.
}

The XML-based syntax for RDF
represents triples, but not named graphs.

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:schema="http://schema.org/">
  <rdf:Description rdf:about="http://dbpedia.org/resource/Ted_Nelson">
    <schema:givenName>Ted</schema:givenName>
  </rdf:Description>
  <rdf:Description rdf:about="http://dbpedia.org/resource/Tim_Berners-Lee">
    <schema:givenName>Tim</schema:givenName>
    <schema:knows rdf:resource="http://dbpedia.org/resource/Ted_Nelson"/>
  </rdf:Description>
</rdf:RDF>

JSON-LD is a JSON syntax to represent
an RDF dataset, supporting named graphs.

Is this snippet JSON-LD?
Why (not)?

{
  "name": "Jane Doe",
  "type": "Person",
  "telephone": "(425) 123-4567",
  "url": "http://www.janedoe.com/"
}

And is this snippet JSON-LD?
Why (not)?

{
  "@context": "http://schema.org/",
  "name": "Jane Doe",
  "@type": "Person",
  "telephone": "(425) 123-4567",
  "url": "http://www.janedoe.com/"
}

JSON-LD provides additional interpretation
on top of the JSON specification.

The same RDF can be represented in
infinitely many different ways as JSON-LD.

{
  "@context": "http://schema.org/",
  "@graph": [{
      "id": "http://dbpedia.org/resource/Ted_Nelson",
      "http://schema.org/givenName": "Ted"
    }, {
      "id": "http://dbpedia.org/resource/Tim_Berners-Lee",
      "http://schema.org/givenName": "Tim",
      "foaf:knows": { "id": "http://dbpedia.org/resource/Ted_Nelson" }
    }]
}

Some of those representations
look like regular JSON documents.

{
  "@context": "http://schema.org/",
  "id": "http://dbpedia.org/resource/Tim_Berners-Lee",
  "givenName": "Tim",
  "knows": [{
    "id": "http://dbpedia.org/resource/Ted_Nelson",
    "givenName": "Ted"
  }]
}

JSON-LD documents can be approached
like regular JSON documents.

{
  "@context": "http://schema.org/",
  "id": "http://dbpedia.org/resource/Tim_Berners-Lee",
  "givenName": "Tim",
  "knows": [{
    "id": "http://dbpedia.org/resource/Ted_Nelson",
    "givenName": "Ted"
  }]
}

JSON-LD documents can be approached
as RDF triples (or quads).

PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX schema: <http://schema.org>

dbr:Ted_Nelson schema:givenName "Ted".
dbr:Tim_Berners-Lee schema:givenName "Tim";
                    schema:knows dbr:Ted_Nelson.

Should apps use this code?
Why (not)?

// Retrieve a JSON-LD document
const response = await fetch('https://pod.example/contacts',
    { 'Accept': 'application/ld+json' });
const contacts = await response.json();

// Print the name of the first contact
console.log(contacts.knows[0].givenName);

The appropriate RDF syntax depends on
graph support and client technology.

This RDFa example interleaves
HTML markup with RDF triples.

<div vocab="http://xmlns.com/foaf/0.1/" typeof="Person">
  <p>
    <span property="name">Alice Birpemswick</span>,
    (<a property="mbox" href="mailto:alice@example.com">alice@example.com</a>)
  </p>
  <ul>
    <li property="knows" typeof="Person">
      <a property="homepage" href="https://example.com/bob/">Bob</a>
    </li>
    <li property="knows" typeof="Person" resource="https://example.com/people/#eve">
      <span property="name">Eve</span>
    </li>
  </ul>
</div>

The extracted RDFa data is regular RDF
that can be converted to other formats.

[] a foaf:Person;
   foaf:name "Alice Birpemswick".
   foaf:mbox <mailto:alice@example.com>;
   foaf:knows [ a foaf:Person;
                foaf:homepage <https://example.com/bob/> ],
              <https://example.com/people/#eve>;

<https://example.com/people/#eve> a foaf:Person;
    foaf:name "Eve".
    

RDF on the Web can be found in webpages
and through content negotiation.

Interoperability challenges in Solid
are solved through Linked Data in RDF.

With RDF, every piece of data
can link to any other piece of data.

{
  "@context":  "https://www.w3.org/ns/activitystreams",
  "id":        "#ruben-likes-stirrups",
  "type":      "Like",
  "actor":     "https://ruben.verborgh.org/profile/#me",
  "object":    "https://www.stirrupshotel.co.uk/#this",
  "published": "2022-07-25T08:00:00Z"
}

Data shapes and their semantics
enable layered compatibility.

{
  "@context":  "https://www.w3.org/ns/activitystreams",
  "id":        "#ruben-likes-stirrups",
  "type":      "Like",
  "actor":     "https://ruben.verborgh.org/profile/#me",
  "object":    "https://www.stirrupshotel.co.uk/#this",
  "published": "2022-07-25T08:00:00Z"
}

Concatenate different source data
to connect knowledge graphs across Pods.

{
  "@context":  "https://www.w3.org/ns/activitystreams",
  "@graph": [{
    "type":      "Like",
    "actor":     "https://ruben.verborgh.org/profile/#me",
    "object":    "https://www.stirrupshotel.co.uk/#this",
    "published": "2022-07-25T08:00:00Z"
  },{
    "type":      "Like",
    "actor":     "https://virginiabalseiro.com/#me",
    "object":    "https://www.stirrupshotel.co.uk/#this",
    "published": "2022-07-25T08:05:00Z"
  }]
}

Semantic Web reasoning is an agent’s
ability to verify and discover facts.

RDF Schema is an RDF vocabulary
to model RDF vocabularies.

RDFS defines the basic building blocks
to construct RDF vocabularies.

rdfs:label is a property that gives
a human-readable name to a resource.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

foaf:knows rdfs:label "knows"@en, "kent"@nl, "connaît"@fr.

rdfs:label rdfs:label "label"@en.

rdf:type is a property stating that
resource is an instance of a class.

<#me> rdf:type foaf:Person.
rdf:type rdf:type rdf:Property.

# Turtle and TriG allow a in predicate position
<#me> a foaf:Person.
rdf:type a rdf:Property.

rdfs:subClassOf is a property stating
all members of a class belong to another.

<#Developer> a rdfs:Class.
foaf:Person a rdfs:Class.
rdfs:Resource a rdfs:Class.
rdfs:Class a rdfs:Class.

<#Developer> rdfs:subClassOf foaf:Person.
foaf:Person rdfs:subClassOf foaf:Agent.
foaf:Person rdfs:subClassOf rdfs:Resource.
rdfs:Class rdfs:subClassOf rdfs:Resource.

rdfs:domain is a property that states
the class of possible subjects of a property.

foaf:img rdfs:domain foaf:Person.
foaf:img rdfs:domain foaf:Resource.
rdf:type rdfs:domain rdfs:Resource.

rdfs:domain rdfs:domain rdf:Property.

rdfs:range is a property that states
the class of possible objects of a property.

foaf:img rdfs:range foaf:Image.
foaf:img rdfs:range foaf:Resource.
rdf:type rdfs:range rdfs:Class.
rdf:type rdfs:range rdfs:Resource.

rdfs:range rdfs:range rdfs:Class.

rdfs:subPropertyOf is a property stating
a property is more specific than another.

<#hasFriend> rdfs:subPropertyOf foaf:knows.
rdfs:range rdfs:subPropertyOf rdfs:seeAlso.
rdfs:domain rdfs:subPropertyOf rdfs:seeAlso.

RDFS reasoners can make entailments
based on the RDFS semantics.

For example, the presence of

<#Tim> foaf:knows <#Wendy>.
foaf:knows rdfs:domain foaf:Person.

will result in an extra triple

<#Tim> a foaf:Person.

Knowledge of RDFS is all you need
to understand most vocabularies.

To get started, try reading these vocabularies:

The Web Ontology Language (OWL) provides concepts for detailed ontologies.

OWL defines additional constraints
for individuals, properties, and classes.

Typical properties can either take
a literal or a named node as object.

Inverse properties express a triple
in the opposite direction.

A functional property restricts the objects
for a given subject to be identical.

What happens when
we put this into a reasoner?

ex:Julia ex:hasSpouse ex:Cathy.
ex:Julia ex:hasSpouse ex:John.
ex:hasSpouse a owl:FunctionalProperty.

Perhaps counterintuitively, the conclusion is:

ex:Cathy owl:sameAs ex:John.

To arrive at a contradiction, explicitly define inequality:

ex:Cathy owl:differentFrom ex:John.

OWL allows defining classes
based on (properties of) other classes.

ex:Single owl:equivalentClass [ a owl:Class;
    owl:intersectionOf (foaf:Person, [
        a owl:Class, owl:Restriction;
        owl:onProperty ex:hasPartner;
        owl:maxCardinality 0
    ])
].

OWL reasoners can make entailments
based on the OWL semantics.

For example, the presence of

<#me> ex:hasSpouse <#SignificantOther>.

together with the earlier class restrictions
ensures the following triple cannot be true:

<#me> a ex:Single.

Some reasoners are tailored to a task,
others can/need to be extended.

Notation3 (N3) is a rule-based language
defined as a superset of Turtle.

We can define rules
for very specific situations.

Defining rules at a higher level
increases their reusability.

Defining rules at the ontological level
makes a vocabulary declarative.

Download these slides
to try things yourself.

go.verborgh.org/rdf-solid-2022

Use a reasoner to uncover
hidden knowledge in existing data.

What is the difference
between GraphQL and SPARQL?

SPARQL closely resembles GraphQL:
it is both a query language and an API.

GraphQL queries only have meaning
with respect to one source.




# List 10 people and their names
{
  person(first:10) {
    name
  }
}

GraphQL queries only have meaning
with respect to one source.




# List 10 people and their names
{
  users(first:10) {
    fullName
  }
}

GraphQL queries only have meaning
with respect to one source.




# List 10 people and their names
{
  friends(first:10) {
    displayName
  }
}

SPARQL queries have universal meaning
across all possible sources.

PREFIX dbo:  <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

# List 10 people and their names
SELECT * {
  ?person a dbo:Person;
          rdfs:label ?name.
}
LIMIT 10

SPARQL Protocol And RDF Query Language: enable querying & updating RDF datasets.

This query finds artists
influenced by Picasso.

PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX dbo: <http://dbpedia.org/ontology/>

SELECT ?name ?person WHERE {
  ?person a dbo:Artist.
  ?person foaf:name ?name.
  ?person dbo:influencedBy dbr:Pablo_Picasso.
}

A query engine tries to find mappings
that satisfy the full basic graph pattern.

The dataset must contain these triples
after substituting the variables:

SELECT query
returns the variable mappings.

A CONSTRUCT query
returns matching triples.

An ASK query returns a boolean stating
whether the pattern exists in the dataset.

DESCRIBE query returns (non-specified)
contextual information for resources.

In addition to only basic graph patterns,
SPARQL queries can contain modifiers.

Does the null for ?spouse
make Charles Sheeler an ex:Single?

We can separate language from API:
this query runs partially client-side.

The client-side engine especially shines
when executing cross-source queries.

Describe photos in your ontology,
then query them using FOAF.

Below are some useful hints
for the query task.

Don’t fight Linked Data. Don’t fight RDF.
Use Linked Data to fight complexity.