Skip to content

Instantly share code, notes, and snippets.

Last active September 20, 2023 15:30
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save niklasl/4f52c32ef2d888c172c8584e36c24610 to your computer and use it in GitHub Desktop.

Blank Graphs for Quotation and Annotation


Note: In this document, the phrase "blank graphs" means "graphs named by bnodes".

This is a proposal for using the existing notion of blank graphs from RDF 1.1, and then base the RDF-star syntax upon that. This includes moving away from quoted terms and the direction defined by those. The question on whether or not we can do this without more defined semantics for at least blank graphs is also explored.

For RDF 1.2, we may be able do this within the existing charter, provided that it can be read to allow for defining quoted and/or annotated triples as a special case of what blank graphs already are for.

This proposal -- since it's based on syntax for named graphs -- only calls for changes to the TriG and SPARQL grammars. Turtle and N-triples cannot describe named graphs, so they are unable to express quotations. N-quads is unaffected since it will work as is. JSON-LD may be affected since the convenience forms of annotation and quotation dash (see below) should be available there too.

Issues at Hand

There are several issues with RDF-star as defined by the Community Group report:

  1. Most use cases don't call for opacity; some for full; some argue for publisher and/or consumer choice (and TEPs don't seem to fit the bill for that either; since only the publisher can control that).
  2. The fact that triples are being added as terms to RDF has been criticized as too complex (them being recursive; see below), or counter-productive (adding new concepts instead of refining existing ones).
  3. These terms seem to be types (just as IRI:s are), which has also been questioned (e.g. requiring occurrences "behind" the triples to be explicitly linked to from the term). Notably, the seminal example is wrong under this interpretation and had to be amended. Will this mistake reoccur repeatedly if RDf-star annotations have wide adoption?
  4. For all this, there is no way to succinctly talk about multiple triples at once. Something named graphs can be used for.
  5. There is no relationship between quoted triples and named graphs.

Such concerns have been raised from members of the wider RDF community (such as Tim Berners-Lee, Dan Brickley and Pat Hayes), as well as from members of the RDF-star Working Group, both to the mailing lists, at GitHub and at TPAC.

Also noteworthy is that the JSON-LD community has been using named graphs, including blank graphs, for years in various production contexts. Of significance, it's been used for signing sets of statements. See Verifiable Credentials, which is a deployed standard used in the wild. This is something that RDF is general is still unable to cater for. The VC community is also a driving force behind the RDF Dataset Canonicalization effort, which aims to address that.

We must not make standards out of touch with the wider community. Of course, there are many communities to consider, such as the property graph community; as well as the early adopters of RDF-star, such as Ontotext GraphDB.

But the latter is a different case. Deploying technology before it is standardized is done at your own risk. Things may change. And stable libraries (i.e. at 1.0 or above) implementing draft technology should not make such experimental features available by default. The Verifiable Credentials on the other side, uses JSON-LD 1.1, a stable W3C Recommendation.

Recursive Terms

Quoted triples originated in Foundations of an Alternative Approach to Reification in RDF, which solely focused on making terms of triples to replace reification. It did not address named graphs.

The notion of a recursive term is problematic. With this, the previously explicitly flat substrate of N-triples would be extended to support a syntactically recursive structure. This adds complexity to the low-level RDF representation. This, for example, would be one valid N-triple row:

<< << << _:start <urn:x:value> "1" >> <urn:x:value> "2" >> <urn:x:value> "3" >> <urn:x:value> "4" .

Compare this to named graphs, which just extended the triple structure with one more item, forming a quad. No new terms. The above is a complex structure. The below is a simple set of N-quads:

_:start <urn:x:value> "1" _:g1 .
_:g1 <urn:x:value> "2" _:g2 .
_:g2 <urn:x:value> "3" _:g3 .
_:g3 <urn:x:value> "4" .

Alternative Options

There are two existing options on the table, from RDF 1.1:

  • A. Go back to the most basic of forms: standardize only syntactic sugar for reification.
  • B. Leverage the existing support for blank graphs, and base RDF-star semantics and syntactic sugar on that.

Either option excludes adding the complexity of recursive triple terms to the core of RDF.

Option A: Just Reification

While reification works, and syntactic sugar could make it much easier to handle, it arguably doesn't make things much better. It also came about before named graphs, and is not aligned with that.

But there is a possible relationship with singleton graphs; see below. Given that, the following considerations on reification may be valuable also for option B.

Reification: Type or Token?

Reifications are occurrences of triples, not "types". This is something seen as useful by e.g. the PG community.

However, using OWL, this could be an opt-in method for defining triple types if you need to:

ex:Statement a owl:Class ;
  rdfs:subClassOf rdf:Statement ;
  owl:hasKey (ex:subject ex:predicate ex:object) .

ex:subject a owl:FunctionalProperty ; rdfs:domain ex:Statement ; rdfs:subPropertyOf rdf:subject .
ex:predicate a owl:FunctionalProperty ; rdfs:domain ex:Statement ; rdfs:subPropertyOf rdf:predicate .
ex:object a owl:FunctionalProperty ; rdfs:domain ex:Statement ; rdfs:subPropertyOf rdf:object .

Reification: Opacity?

Reification has no opacity in itself.

From RDF 1.1 Semantics:

Reification is not a form of quotation. Rather, the reification describes the relationship between a token of a triple and the resources that the triple refers to.

That is not to say that you cannot quote "uses of names" through it.

Concretely, this is a kind of semantic quotation:

<lexluthor> :believes [ a rdf:Statement ;
    rdf:subject [ skos:exactMatch <superman> ] ;
    rdf:predicate owl:sameAs ;
    rdf:object [ skos:exactMatch <clarkkent> ]
  } .

Each blank node here denote something which is said to be a specific identity. The subject and object are thus two tokens for some sense, just as the statement is a token of some meaning.

(And there are many kinds of quotes. But that is entering a philosophic and linguistic permathread. While I believe Frege solved some of it with Sense and reference; let's leave this at that.)

As said, just a nicer syntax reification leaves a lot to be wished for. Let's do better.

Option B: Leverage Blank Graphs

We can solve most issues by making it more convenient to use blank graphs in RDF 1.2. These are already allowed in the TriG syntax, and defined in RDF 1.1. Concepts as:

Zero or more named graphs. Each named graph is a pair consisting of an IRI or a blank node (the graph name), and an RDF graph. Graph names are unique within an RDF dataset.

The proposed usage below includes -- but is not limited to -- using them for annotation of statements as singleton graphs. Then we use that basis to define some or all of the RDF-star syntax for TriG and SPARQL as syntactic sugar.

Nothing else is needed; SPARQL syntax could be minimally altered, and its semantics could possibly go unaltered.

Already Deployed

With blank node identifiers for graphs, we can solve many things, maybe even without requiring a semantics for named graphs, or by only defining semantics for blank graphs.

TriG already supports bnodes for named graphs (both as blank id:s and the empty blank node form).

This form is also already supported in JSON-LD (since 1.0; extended syntax in 1.1 as graph container). Widely deployed via VC.

So with this, we could actually punt on the semantics, i.e. add nothing beyond syntax. This is because, as said, this is already in RDF 1.1. But let's examine the semantics we do have, note what is missing, and assess use cases based on that state of affairs.

Named Graphs Today

Starting with what is already defined, let's examine the list of issues from above:

  1. Opacity: semantically undefined, but SPARQL has mechanisms for choosing graphs. Some implementations support declaring which graphs belong to which dataset (and are transparent within those), as well as if they belong to the union graph or not.
  2. No new terms need to be defined. Named graphs are not recursive.
  3. Named graphs are occurrences of the triples they contain. That is, two distinct named graphs can contain the identical set of triples.
  4. Named graphs are about talking about multiple triples at once.
  5. This is named graphs.

Using Blank Graphs for Quotation

In the following, the RDF-star annotation form is excluded. This form is very useful, so it will be covered in a separate section below.

As a simple example, let's describe the birth date of a person. We have one source which we believe in, and another which we don't trust but want to display.

First, let's see it as RDF-star as currently designed:

<p1> :birthDate "1901" .
# Annotated assertion:
<< <p1> :birthDate "1901" >> :source <book/a> .
# Quoted (non-asserted) statement:
<< <p1> :birthDate "1902" >> :source <wikidata/p1> .

This can be expressed using blank graphs:

<p1> :birthDate "1901" .
# Annotated assertion:
_:g1 { <p1> :birthDate "1901" }
_:g1 :source <book/a> .
# Quoted (non-asserted) statement:
_:g2 { <p1> :birthDate "1902" }
_:g2 :source <wikidata/p1> .

Improved Ergonomics

Blank Graphs as Subjects

To make TriG equally ergonomic, just extend this grammar rule:

[7g]	labelOrSubject	::=	iri | BlankNode


[7g]	labelOrSubject	::=	iri | BlankNode | blankNodePropertyList

Then we can talk about blank graphs without naming them:

<p1> :birthDate "1901" .
[ :source <book/a> ] { <p1> :birthDate "1901" }
[ :source <wikidata/p1> ] { <p1> :birthDate "1902" }

This actually shaves some bytes from the quoted triple form.

It arguably reads "backwards" though, unless you think of the blank note as a "meta header". TriG and SPARQL basically excludes the "graph terms as subjects" form available in Notation 3. We could make room for it, but the above is the simplest change to allow for talking about truly blank graphs.

(To do more may require an assessment of how often blank graphs as subjects will actually be used in the wild. It is possible that such cases are better catered for by the annotation syntax anyway (see further below).)

Blank Graphs as Objects

In fact, altering the rules some more, changing:

[12]	object	::=	iri | blank | blankNodePropertyList | literal


[12]	object	::=	iri | blank | blankNodePropertyList | literal | wrappedGraph

allows for blank graphs as objects:

<p1> :birthDate "1901" .
<book/x> :sourceOf { <p1> :birthDate "1901" } .
<wikidata/p1> :sourceOf { <p1> :birthDate "1902" } .

Blank Graphs are More Than Quoted Triples

It should be pointed out that, obviously, we can use this form to talk about arbitrarily many triples at once. These are just named graphs, named with blank nodes.

(The semantics thereof are interesting; see the section on Blank Graph Semantics below.)

Already in JSON-LD

Note that for JSON-LD 1.1, nothing is needed. It already supports having graphs as subjects:

  "@context": {"@vocab": ""},
  "@graph": [
    {"@id": "p1", "birthDate": "1901"},
      "@graph": {"@id": "p1", "birthDate": "1901"},
      "source": {"@id": "book/x"}
      "@graph": {"@id": "p1", "birthDate": "1902"},
      "source": {"@id": "wikidata/p1"}

and as objects:

  "@context": {"@vocab": ""},
  "@graph": [
      "dc:created": {
        "@value": "2023-05-20T09:14:30Z",
        "@type": "xsd:dateTime"
      "@graph": [
          "@id": "book/x",
          "sourceOf": {
            "@graph": {"@id": "p1", "birthDate": "1901"}
          "@id": "wikidata/p1",
          "sourceOf": {
            "@graph": {"@id": "p1", "birthDate": "1902"}

Nested Graphs?

Note that with the above grammar changes, graph objects would be supported within graphs:

[ dc:created "2023-05-20T09:14:30Z"^^xsd:dateTime ] {

    <book/x> :sourceOf { <p1> :birthDate "1901" } .

    <wikidata/p1> :sourceOf { <p1> :birthDate "1902" } .


But the subject form would require more grammar changes. Thus, this is not supported unless further grammar changes are made:

[ dc:created "2023-05-20T09:14:30Z"^^xsd:dateTime ] {
    [ rdfs:comment "This is an audio book."@en ] {
      <introduction-to-physics> a :Text

This is the most compact form for that, supported by the additions above:

_:g1 { <introduction-to-physics> a :Text }
[ dc:created "2023-05-20T09:14:30Z"^^xsd:dateTime ] {
  _:g1 rdfs:comment "This is an audio book."@en

All of which would look like this in the quoted triple form:

  << <introduction-to-physics> a :Text >> rdfs:comment "This is an audio book."@en
>> dc:created "2023-05-20T09:14:30Z"^^xsd:dateTime .

The usefulness and proliferation of this practise needs further consideration. Most prominently seeing if RDF-star annotations can reduce those patterns.

Most importantly, this is just surface syntax. There's no nesting -- other than the obvious "which triples belong to which graphs" -- just as there is no nesting of blank nodes in any RDF format. Everything flattens out to N-Quads.

It probably makes sense not to cater for deeply nested forms, as these quotes of quotes quickly become illegible for most purposes.

SPARQL With Blank Graphs

Example based on RDF-star patterns for provenance:

SELECT ?claimer (MIN(?conf) as ?minConfidence)
    GRAPH [ :accordingTo ?claimer; :confidence ?conf ] { ?claimer ?p ?o }
GROUP BY ?claimer

Based on RDF-Star: Some biological database use cases:

    GRAPH release:1 {
        GRAPH [ up:attribution ?attr ] {
          ?prot up:fullName "3-beta-hydroxysterol Delta (14)-reductase"
      ?attr up:manual true ;
        up:evidence ECO:0000303 ;
        up:source citation:16784888 .

Star Syntax Revisited: Shorthands for Singleton Graphs

No Quoted Triples

While the << ... >> form could be sugar for singleton graphs, given the alterations above, this is simply not needed.

RDF-star Annotations as Singleton Graphs

The RDF-star annotation syntax works just as well as a shorthand for singleton graph quotations -- that is to eliminate the duplication of an asserted and quoted triple.

Thus, taking an above example:

<p1> :birthDate "1901" .
[ :source <book/a> ] { <p1> :birthDate "1901" }
[ :source <wikidata/p1> ] { <p1> :birthDate "1902" }

This could be further abbreviated to:

<p1> :birthDate "1901" {| :source <book/a> |} .
[ :source <wikidata/p1> ] { <p1> :birthDate "1902" }

Proposal: New Quoted Form

For JSON-LD-star, I've proposed a @qouted keyword to allow for the grouping of multiple statements.

In TriG, we can introduce a quotation dash to achieve this: --. (This is also the comment syntax used in e.g. SQL.)

The grammar modification would be along the lines of going from (the modified version from above):

[12]	object	::=	iri | blank | blankNodePropertyList | literal | wrappedGraph


[12]	object	::=	'--'? (iri | blank | blankNodePropertyList | literal | wrappedGraph)

Using -- will "comment out" or quote the object, which "detaches" the statement it completes from the asserted graph and put it in a blank graph. This can then be further annotated using the annotation syntax:

<introduction-to-physics> a -- :Text {| rdfs:comment "This is an audio book."@en |} .


[ rdfs:comment "This is an audio book."@en ] { <introduction-to-physics> a :Text }

This looks much more appealing with more data. Consider this using the current RDF-star proposal:

<introduction-to-physics> a :Text ;
  bf:classification <literature-education-physics> .

<< <introduction-to-physics> a :Text >> rdfs:comment "This is an audio book."@en .
  << <introduction-to-physics> a :Text >> rdfs:comment "This is an audio book."@en
>> dc:created "2023-05-20T09:14:30Z"^^xsd:dateTime .

<< <introduction-to-physics> a :Audio >>
    rdfs:comment "This is probably true."@en .

  << <introduction-to-physics> a :Audio >> rdfs:comment "This is probably true."@en
>> dc:created "2023-05-20T09:14:59Z"^^xsd:dateTime .

<< <introduction-to-physics> bf:classification <literature-education-physics> >>
  dc:creator <annif> ;
  dc:date "2023-05-20T08:44:06Z" .

<< <introduction-to-physics> bf:classification <literature-education-magic> >>
  dc:creator <me> ;
  dc:date "2023-09-16T12:59:10Z"^^xsd:dateTime .

which arguably isn't any better than blank graphs:

<introduction-to-physics> a :Text ;
  bf:classification <literature-education-physics> .

_:stmt1 { <introduction-to-physics> a :Text } # Assertion
_:stmt1 rdfs:comment "This is an audio book."@en .

_:stmt0 { _:stmt1 rdfs:comment "This is an audio book."@en }
_:stmt0 dc:created "2023-05-20T09:14:30Z"^^xsd:dateTime .

_:stmt2 { <introduction-to-physics> a :Audio }
_:stmt2 rdfs:comment "This is probably true."@en .
_:stmt3 { _:stmt2 rdfs:comment "This is probably true."@en }
_:stmt3 dc:created "2023-05-20T09:14:59Z"^^xsd:dateTime .

_:stmt4 { <introduction-to-physics> bf:classification <literature-education-physics> }
_:stmt4 dc:creator <annif> ;
  dc:date "2023-05-20T08:44:06Z"^^xsd:dateTime .

_:stmt5 { <introduction-to-physics> bf:classification <literature-education-magic> }
_:stmt5 dc:creator <me> ;
  dc:date "2023-09-16T12:59:10Z"^^xsd:dateTime .

By using RDF-star annotations we can both remove a lot of repeated quotes, and annotate quoted objects, using --. The result is both compact and legible (once you're used to the quotation dash):

<introduction-to-physics> a :Text {|
      rdfs:comment "This is an audio book."@en {|
          dc:created "2023-05-20T09:14:30Z"^^xsd:dateTime |}
        |} ,
    -- :Audio {|
        rdfs:comment "This is probably true."@en {|
          dc:created "2023-05-20T09:14:59Z"^^xsd:dateTime |}
      |} ;
  bf:classification <literature-education-physics> {|
        dc:creator <annif> ;
        dc:date "2023-05-20T08:44:06Z"
      |} ,
    -- <literature-education-magic> {|
        dc:creator <me> ;
        dc:date "2023-09-16T12:59:10Z"^^xsd:dateTime |} .

Proposal: RDF-star Annotation Occurrences

The {| ... |} form appears ergonomic and a primary motivation for many to use RDF-star, albeit for a wide range of reasons. The question is what it affords in use. Given the above semantics, its "misuse" is even mitigated, as the triple annotations become blank graphs; i.e. occurrences.

Only with semantics, e.g. if they are given an explicit rdf:type, can they be types. This is arguable a better balance.

Given occurrence nature of graphs, it makes sense that annotations based on such can also be repeated. The current annotation syntax could be repeated as is (without a separating ,, as that leads to the nest object). But since we're basing these annotations on blank graphs, it makes sense to alter the syntax a bit: {[ ... ]}. Repetition then takes place inside the braces, like: { [ ...] [ ... ] }.

You could even use a bnode id here, to put multiple statements into the same "annotation graph": {_:ggg}. In fact, we can even assert that a statement is in one or more named graphs in this way: {<ggg>}.


<p1> a :Person ;
  :birthDate "1901" {
        [ :source <wikidata/p1> ; :date "2017-01-14" ]
        [ :source <wikidata/p2> ; :date "2023-09-19" ]
    } ,
    -- "1902" {[ :source <book/x> ]} .


<p1> a :Person ; :birthDate "1901" .

[ :source <wikidata/p1> ; :date "2017-01-14" ] { <p1> :birthDate "1901" }
[ :source <wikidata/p2> ; :date "2023-09-19"] { <p1> :birthDate "1901" }
[ :source <book/x> ] { <p1> :birthDate "1902"  }


<p1> a :Person ;
  :name "Some Body" {<wikidata/p1>},
    -- "Some One" {<wikidata/p2>},
  :birthDate "1901" { <wikidata/p1> <wikidata/p2> } ,
    -- "1902" {<book/x>} .


<p1> a :Person ; :name "Some Body" ; :birthDate "1901" .

<wikidata/p1> { <p1> :name "Some Body" ; :birthDate "1901" }
<wikidata/p2> { <p1> :name "Some One"; :birthDate "1901" }
<book/x> { <p1> :birthDate "1902" }

This extends the use of annotations from only being about quoted triples (as blank singleton graphs), to allow for directly presenting the union of multiple graphs describing the same resource.

(While using braces around identifiers like this can take some getting used to, it is reminiscent of the VALUES clause in SPARQL.)

Graph Semantics

Named Graph Semantics

As noted in RDF 1.1: On Semantics of RDF Datasets, there are no semantics for named graphs in RDF 1.1. There are old proposals such as in RDF Graph Literals and Named Graphs, with terms such as rdfs:Graph and rdfg:isGraph that could be revisited. But as said, this can be deferred to RDF 1.3 or later. (It would be useful to update the datasets note though.)

Blank Graph Semantics

We could settle for defining semantics for blank graphs only. While not formally defined, is there any known use of blank-labelled graphs other than for denoting them (as occurrences of triple sets)?

Also from the note on dataset semantics:

RDF 1.1 borrows the notion of RDF dataset from the SPARQL specification [SPARQL11-QUERY], with the notable different that RDF 1.1 allows graph names to be blank nodes.

Since SPARQL 1.1 does not have this notion, it would have to be formalized.

One consideration is whether blank graphs are ever in the union graph (a concept not defined in SPARQL, which has the notion of the default graph and active graph, the former often, but depending on implementation, being the union graph).

I propose no, to make expectations clear, and thus making blank graphs fill exactly the role that quoted triples were intended for (quoted triples simply become the special case of singleton graphs). (This could also provide some room for allowing storage optimizations to be made, by letting blank graphs share space with the named graph they're defined in.)

PROPOSAL: blank graphs MUST NOT be part of the union graph, unless explicitly accepted (e.g. using rdfs:seeAlso, like how owl:imports is used for "accepting" ontologies); or perhaps typed as e.g. ex:Belief.

PROPOSAL: blank graph id:s SHOULD belong to the one graph where they are defined. This makes them a kind of "appendices" to that graph. Presumably, this also allows for logical storage optimizations (again, presumably as what has been done for quoted triples).

We should also consider the semantics of Named Graphs, 2005 p. 6-8.. Some parts may be reformulated to only be about blank graphs. (Note: excluding the blank node sharing rules within this document, which are more lax in in RDF 1.1 and used by e.g. JSON-LD.)

Blank graphs MUST or MAY share bnode with their "defining" graph?

(Note, as per above, that blank graphs are not nested, just as blank nodes are not. You could however define partitive relationships to the blank graphs in an "outer" graph within that, using explicit predicates to declare these relationships.)

Triples as Singleton Graphs?

Is a triple a (named or blank) singleton graph?

The [Named Graphs, 2005] says:

A ‘reified statement’ [3] is a single RDF statement described and identified by a URI reference. Within the framework of this paper, it is natural to think of this as a named graph containing a single triple, i.e. a named triple. With this convention, the subject of rdfg:subGraphOf can be a reified triple, and the property can be used to assert that a named graph contains a particular triple. This provides a useful connection with the traditional use of reification and a potential migration path.

RDF Semantics 1.1 says:

A triple is identified with the singleton set containing it, so that each triple in a graph is considered to be a subgraph.

But does the fact that "the axiom of regularity together with the axiom of pairing implies that no set is an element of itself", conflict with this?

That is, is there a difference between a triple and a singleton graph? Or is a graph not a set of triples, represented by a set of triples?

  • Such that the simplest not-empty graph is one arc (the "meaning" of the triple)?
  • But is an empty graph the empty set, or true?
  • If they're the same, we know that << :s :p :o >> rdfg:subGraphOf { :s :p :o }?

Unify Singleton Graphs and Reification

In the aforementioned [Named Graphs, 2005], a singleton graph could entail a reified triple:

Named triples may be combined with RDF reification, noting the possibility expressed in RDF Sematics [3]:

Semantic extensions MAY limit the interpretation of these so that a triple of the form

aaa rdf:type rdf:Statement .

is true in I just when I(aaa) is a token of an RDF triple in some RDF document, and the three properties, when applied to such a denoted triple, have the same values as the respective components of that triple. In this case, any interpretation conforming with a set of named graphs including a named triple, will satisfy the reification of that triple.

Such that:

[] { <p1> a :Person }

could entail:

[ a rdf:Statement ;
  rdf:subject <p1> ;
  rdf:predicate rdf:type ;
  rdf:object :Person
] { <p1> a :Person }

Singleton Graph: Type or Token?

With this possible reification entailment, combined with the above owl:hasKey suggestion for subclasses of rdf:Statement, just typing a singleton graph might be enough lift it from a token to a type. If that is desirable. Use cases seem to ask more for spurious annotations than disciplined triples as types, so perhaps this is not necessary.

Blank Graphs: Opacity?

Graphs are isolated unless accepted (a word used in [Named Graphs, 2005] (also elsewhere?)) in the (a) union graph, and thus "conditionally"(?) combinable. How and which graphs of a given dataset are accepted is unspecified? It is practically clear that it is only in use that entailment and opacity come into play.

Apart from what I believe is a better option for user-explicit opacity (see above), there are more options here, perhaps "thanks" to undefined dataset semantics... See also rdf:NeutralGraph from RDF Surfaces...

While there may be a lot that could be done here, at least some of it can be done solely by using OWL. We may need more entailment rules for blank graphs (as suggested above), but that doesn't have to be done in RDF 1.2. Care must be taken in what we define so that it works with these future possibilities of course, so we should gain some exploratory experience of what they entail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment