Re: shapes-ACTION-35: Proposal for lists (ISSUE-99 and ISSUE-119)

On 02/18/2016 04:36 PM, Holger Knublauch wrote:
> This looks identical to what both Simon and I suggested independently, see


Simon's first proposal in his message would treat list values as a special
case, so that sh:class ex:Person would validate a list of nodes whose SHACL
type was ex:Person.  Very, very different.

Simon's second proposal in his message is indeed very similar in spirit.  It
does not, however, describe how it should work and also appears to retain the
special treatment of sh:class rdf:List.

Your proposal fills in some of the details missing in Simon's second proposal.
 However, it is different from Simon's proposal in that it is a property
constraint, not a general constraint.  Your proposal does not do a full check
on whether the list is well-formed.  As well, you are proposing something that
is not in the core language, and are not proposing removing the special
treatment of sh:class rdf:List.

> This would reopen ISSUE-119 which we previously closed by stating no fix. The
> only reason to reopen this to me would be that we might then have an official
> response to the question "how to state that the range of a property is rdf:List":
> ex:ListPropertyShape
>     a sh:Shape ;
>     sh:property [
>         # Values of this property must be lists of type ex:Person
>         sh:predicate ex:myListProperty ;
>         sh:memberShape [
>             sh:constraint [
>                 sh:class ex:Person ;
>             ]
>         ]
>     ] .
> In a sense we already have two alternatives to state that something is a list,
> namely using rdfs:range (or OWL) or even sh:valueShape with a suitable shape
> that walks the rdf:List structure. This may be sufficient.
> I still predict people will stumble over why they cannot use sh:class
> rdf:List. 

Well, people can certainly use sh:class rdf:List.  It will just act like every
other class.

> Also it doesn't help tools that try to make sense of shape
> definitions. How many more special cases do we want to require here? A tool
> that tries to figure out the range of a property must look for:
> - sh:datatype
> - sh:datatypeIn
> - sh:class
> - sh:classIn
> - sh:directType
> - owl:allValuesFrom
> - rdfs:range
> - and soon "if sh:memberShape exists then infer rdf:List".
> This is becoming dangerously unusable in practice, inefficient to handle and
> impossible to justify to users.

I disagree completely.

Of course, there is a solution that is much more uniform.  The working group
has decided to not go that way.

> Overall this is just another instance of the tension between formal rigidity
> and practical usefulness.

I completely disagree.  The existing special cases for rdf:List and
rdfs:Resource are, in my opinion, both impractical and misleading.  It is much
better for users to have clear, compact, and useful constructs, and special
cases damage all of theses.

> Also, we have not yet talked about the other special case in the current
> draft: if sh:class is rdfs:Resource then we currently allow any blank node or
> IRI even if it has no rdf:type. How else would we specify that? It would
> require a complex sh:or between two sh:nodeKind constraints - very ugly. Shall
> we add yet another special syntax just to keep sh:class "clean"?

Not at all.   Where is the need to use rdfs:Resource for "anything"?  This can
simply be done by saying .... nothing!

> Holger


> On 19/02/2016 8:33, Peter F. Patel-Schneider wrote:
>> The following data graph
>> @prefix rdf: <> .
>> @prefix ex: <> .
>> ex:l1 rdf:first ex:l2 .
>> ex:l1 rdf:rest ex:l1 .
>> ex:l1 rdf:rest ex:l2 .
>> currently validates against
>> @prefix sh: <> .
>> @prefix rdf: <> .
>> @prefix ex: <> .
>> ex:s1 a sh:Shape ;
>>    sh:scopeNode ex:l1 ;
>>    sh:constraint [ a sh:Constraint ; sh:class rdf:List ] .
>> This special cases rdf:List, but in a way that is not useful at all, as it
>> validates something that should not be considered to be a list.  If lists
>> are to be treated specially, SHACL should do something reasonable for them.
>> A reasonable approach to supporting lists is to have a special constraint
>> construct for lists whose elements validate against a shape, as in
>> ex:personList a sh:Shape ;
>>    sh:constraint [ a sh:Constraint ;
>>      sh:list [ a sh:Shape;
>>        sh:constraint [ a sh:Constraint; sh:class ex:Person ] ] ] .
>> The shape here is true of a node if it is a single-tailed finite RDF list
>> and each of the list elements validates against the embedded shape.  This is
>> the case for a node precisely when the transitive-reflexive closure of
>> rdf:next from the node contains rdf:nil and for each node in the closure it
>> must be the case that either the node is rdf:nil and it has no outgoing
>> rdf:next or rdf:first edges or if it is not rdf:nil then the node has
>> precisely one outgoing rdf:next edge and precisely one outgoing rdf:first
>> edge and the object of the outgoing rdf:first edge has SHACL type ex:Person.
>> This construct can validate lists that have different kinds of conditions,
>> such as lists of blank nodes
>> ex:blankList a sh:Shape ;
>>    sh:constraint [ a sh:Constraint ;
>>      sh:list [ a sh:Shape;
>>        sh:constraint [ a sh:Constraint; sh:nodeKind sh:BlankNode ] ] ] .
>> or lists of childless people
>> ex:childlessList a sh:Shape ;
>>    sh:constraint [ a sh:Constraint ;
>>      sh:list [ a sh:Shape;
>>        sh:constraint [ a sh:Constraint; sh:class ex:Person ] ;
>>        sh:property [ a sh:PropertyConstraint;
>>          ex:predicate ex:child; ex:maxCount 0 ] ] ] .
>> It can even validate lists that have no conditions on their elements, but
>> just must be well-formed lists
>> ex:anyList a sh:Shape ;
>>    sh:constraint [ a sh:Constraint ; sh:list [ a sh:Shape ] ] .

Received on Friday, 19 February 2016 01:13:13 UTC