Copyright © 2014 W3C. This document is available under the W3C Document License. See the W3C Intellectual Rights Notice and Legal Disclaimers for additional information.
Shape Expressions associate RDF graphs with labeled patterns called "shapes". Shapes can be used for validation, documentation and transformation of RDF data.
Shape Expressions express formal constraints on the content of RDF graphs and is intended to be used to validate RDF documents, communicate expected graph patterns for interfaces and to generate forms and validation code. This document describes the formal semantics of the Shape Expressions language through the use of the Z Specification Language. The accompanying Shape Expressions Primer provides an informal introduction to the language.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document describes the Shape Expressions langauge developed as a community effort. It is being submitted to W3C so that it can inform the development of a future RDF Data Shape specification.
By publishing this document, W3C acknowledges that the Submitting Members have made a formal Submission request to W3C for discussion. Publication of this document by W3C indicates no endorsement of its content by W3C, nor that W3C has, is, or will be allocating any resources to the issues addressed by it. This document is not the product of a chartered W3C group, but is published as potential input to the W3C Process. A W3C Team Comment has been published in conjunction with this Member Submission. Publication of acknowledged Member Submissions at the W3C site is one of the benefits of W3C Membership. Please consult the requirements associated with Member Submissions of section 3.3 of the W3C Patent Policy. Please consult the complete list of acknowledged W3C Member Submissions.
This version has no official status. It corrects multiple Z Notation rendering errors which were caused by manually translating LaTeX to HTML. The Z Notation rendering in this version was generated by automatically translating LaTeX to HTML using XSLT. These XSLT scripts are available in the w3c/ShEx project hosted on GitHub: https://github.com/w3c/ShEx.
This version only corrects the Z Notation rendering errors present in the original W3C Member Submission. Stylistic and semantic errors remain.
The Shape Expressions Language (ShEx) is used to specify formal constraints on the content of RDF graphs and are intended to be used to validate RDF documents, communicate expected graph patterns for interfaces and to generate forms and validation code. ShEx can be used to:
Information about the use, grammar and syntax of ShEx can be found at http://www.w3.org/2013/ShEx/. This document describes the formal semantics of the ShEx language using the Z specification language, beginning with a Z specification of the characteristics of an RDF Graph that are referenced by ShEx.
The formal definition for an RDF graph in RDF 1.1 Concepts and Abstract Syntax[RDF11-CONCEPTS]:
“An RDF graph is a set of RDF Triples”
“An RDF triple consists of three components:
- the subject, which is an IRI or a blank node
- the predicate, which is an IRI
- the object, which is an IRI, a literal or a blank node”
“... IRIs, literals and blank nodes are distinct and distinguishable.”
provides a definition in Z:
Graph ==ℙTriple |
The ShEx language treats IRIs and blank nodes as primitive types, which are defined as Z free types:
[IRI, BlankNode] |
The ShEx language can express constraints on both the type and content of literals, which are modeled separately:
“A literal in an RDF graph consists of two or three elements:
This is modelled by String and LanguageTag as free types:
[String, LanguageTag] |
TypedLiteral≙ |
[lexicalForm:String ; dataType:IRI | |
dataType≠ XSD_String] |
PlainLiteral≙ |
[lexicalForm:String ; dataType:IRI; langTag:LanguageTag | |
dataType = XSD_String] |
RDFLiteral ::= pl《PlainLiteral》| tl《TypedLiteral》 |
“IRIs, literals and blank nodes are collectively known as RDF terms
RDFTerm ::= |
iri《IRI》| |
literal《RDFLiteral》| |
bnode《BlankNode》 |
Triple | ||
s,p,o:RDFTerm | ||
iri⋅s∈ IRI∨ bnode⋅s∈ BlankNode | ||
iri⋅p∈ IRI | ||
iri⋅o∈ IRI∨ bnode⋅o∈ BlankNode∨ literal⋅o∈ RDFLiteral | ||
The ShEx language uses the following functions:
– return set of triples in a graph triples whose subject is a given RDFTerm
triplesForSubject:RDFTerm→ Graph→ Graph | ||
∀ subj:RDFTerm; g:Graph • triplesForSubject subj g = {t:g | t.s = subj } | ||
– return set of triples in a graph triples whose object is a given RDFTerm
triplesForObject:RDFTerm→ Graph→ Graph | ||
∀ obj:RDFTerm; g:Graph • triplesForObject obj g = {t:g | t.o = obj } | ||
The following URIs are referenced explicitly in the ShEx implementation:
XSD_String:IRI | |
SHEX_IRI:IRI | |
SHEX_BNODE:IRI | |
SHEX_LITERAL:IRI | |
SHEX_NONLITERAL:IRI |
The above definitions of Graph, Triple, RDFTerm and their components will now be used to describe the relationship between a ShEx Schema and an RDF graph.
A Shape Expression Schema is a collection of labeled rules where exactly one rule in the collection is identified as the outermost or “starting” rule. In addition, any rule that is referenced within the Schema is also itself a member of the Schema Formally:
Schema | ||
rules:Label⇸Rule | ||
start:Label | ||
start∈ domrules | ||
∀ r:ranrules • | ||
(r∈ rangroup⇒ (group⋅r).rule∈ domrules)∧ | ||
(r∈ ranand⇒ ran(and⋅r)⊆ domrules)∧ | ||
(r∈ ranxor⇒ ran(xor⋅r)⊆ domrules)∧ | ||
(r∈ ranarc∧ (arc⋅r).valueSpec∈ ranvalueRef⇒ | ||
(valueRef⋅(arc⋅r).valueSpec)∈ domrules) | ||
While existing ShEx implementations define a rule Label as being either an IRI or a BlankNode, the type of Label does not impact the evaluation semantics. For our purposes, we can simply define it as a separate free type:
[Label] |
The validity of a given RDF Graph is determined by taking the start Rule of a ShEx Schema and a reference IRI and evaluating the validity of the Rule against the supplied graph.
Formally, the evaluate function takes a Schema, a Graph and a reference IRI and, if the start Rule in the Schema, in the context of the starting Schema and graph, returns either nomatch (z) or pass (p) then the function returns pass. In all other cases, the function returns fail (f ).
evaluate:Schema→ Graph→ IRI→ OptValidity | ||
∀ s:Schema; g:Graph; i:IRI; v:OptValidity; ec:EvalContext | | ||
ec.graph = g∧ ec.schema = s • | ||
evaluate s g i = | ||
ifevalRule ec (iri i) (s.rules s.start)∈ {z,p} | ||
thenpelsef | ||
A ShEx Rule is a set of constraints that can be evaluated against a reference RDFTerm in the context of a given Schema and RDF Graph:
EvalContext≙[schema:Schema; graph:Graph] |
Formally, the evalRule function takes an EvalContext, a reference RDFTerm and a Rule and returns one of the following:
OptValidity ::=p|f|z|∅|ε |
Rule ::= |
arc《ArcRule》| |
rarc《RevArcRule》| |
group《GroupRule》| |
and《AndRule》| |
xor《XorRule》 |
evalRule:EvalContext→ RDFTerm→ Rule→ OptValidity | ||
∀ ec:EvalContext; i:RDFTerm; r:Rule • evalRule ec i r = | ||
ifr∈ ranarc | ||
thenevalArcRule ec i (arc⋅r) | ||
elseifr∈ ranrarc | ||
thenevalRevArcRule ec i (rarc⋅r) | ||
elseifr∈ rangroup | ||
thenevalGroupRule ec i (group⋅r) | ||
elseifr∈ ranand | ||
thenevalAndRule ec i (and⋅r) | ||
else | ||
evalXorRule ec i (xor⋅r) | ||
evalRule':EvalContext→ RDFTerm→ Label→ OptValidity | ||
∀ ec:EvalContext; l:Label • l∈ domec.schema.rules | ||
The ArcRule is used to select the subset of the graph having a given predicate or predicates and to determine whether the cardinality and/or “type” of this subset matches a supplied criteria. The rule itself consists of a PredicateFilter to select the triples, an ObjectSpecification to evaluate the result, an optional min and max cardinality and a (possibly empty) set of Actions:
ArcRule | ||
filter:PredicateFilter | ||
valueSpec:ObjectSpecification | ||
min, max:optional[ℕ] | ||
actions:ℙAction | ||
(# min = 1∧ # max = 1)⇒ value min≤value max | ||
evalArcRule:EvalContext→ RDFTerm→ ArcRule→ OptValidity | ||
∀ ec:EvalContext; s:RDFTerm; ar:ArcRule; sg:Graph | | ||
sg = evalPredicateFilter ar.filter (triplesForSubject s ec.graph) • | ||
evalArcRule ec s ar = | ||
ifevalCardinality sg ar.min ar.max≠ p | ||
thenevalCardinality sg ar.min ar.max | ||
elseifevalObjectSpecification ec ar.valueSpec sg≠ p | ||
thenevalObjectSpecification ec ar.valueSpec sg | ||
else | ||
dispatch ar.actions sg ec | ||
A PredicateFilter can be one of:
IRIorStem ::= iosi《IRI》| ioss《IRIstem》 |
PredicateFilter ::= pfIRI《IRIorStem》| pfWild《ℙIRIorStem》 |
[IRIstem] |
IRIstemRange:IRIstem⇸ℙIRI | ||
evalPredicateFilter:PredicateFilter⇸Graph⇸Graph | ||
∀ f:PredicateFilter; g:Graph • evalPredicateFilter f g = | ||
iff∈ ranpfIRIthenevalIRIorStem (pfIRI⋅f) g | ||
elseevalWild (pfWild⋅f) g | ||
evalIRIorStem:IRIorStem⇸Graph⇸Graph | ||
∀ e:IRIorStem; g:Graph • evalIRIorStem e g = | ||
ife∈ raniosithen{t:g | iri⋅t.p = iosi⋅e } | ||
else{t:g | iri⋅t.p∈ IRIstemRange (ioss⋅e) } | ||
evalWild:ℙIRIorStem⇸Graph⇸Graph | ||
∀ es:ℙIRIorStem; g:Graph • evalWild es g = | ||
{t:g | t∉ ⋃{e:es • evalIRIorStem e g} } | ||
ObjectSpecification specifies a set of possible values for an RDFTerm and takes one of the following forms:
MatchValue ::= |
mviri《IRI》| |
mviris《IRIstem》| |
mvlit《RDFLiteral》 |
ObjectSpecification ::= |
valueType《IRI》| |
valueSet《ℙMatchValue》| |
osWild《ℙMatchValue》| |
valueRef《Label》 |
– evaluates the cardinality the supplied graph.
evalCardinality:Graph→ optional[ℕ]→ optional[ℕ]→ OptValidity | ||
∀ g:Graph; min, max:optional[ℕ] • evalCardinality g min max = | ||
if# min = 1∧ # g = 0∧ value min = 0 | ||
thenz | ||
elseif# g = 0 | ||
then∅ | ||
elseif(# min = 1∧ # g < value min)∨ | ||
(# max = 1∧ # g > value max) | ||
thenf | ||
elsep | ||
evalObjectSpecification – returns pass (p) if all of the triples in a Graph match the supplied ObjectSpecification, otherwise fail (f )
evalObjectSpecification:EvalContext→ ObjectSpecification→ Graph→ | ||
OptValidity | ||
∀ ec:EvalContext; os:ObjectSpecification; g:Graph • | ||
evalObjectSpecification ec os g = | ||
if∀ t:g • evalObjectSpecificationTriple ec os t.o =p | ||
thenp | ||
elsef | ||
evalObjectSpecificationTriple:EvalContext→ ObjectSpecification→ | ||
RDFTerm→ OptValidity | ||
∀ ec:EvalContext; os:ObjectSpecification; n:RDFTerm • | ||
evalObjectSpecificationTriple ec os n = | ||
ifos∈ ranvalueTypethen | ||
evalValueType (valueType⋅os) n | ||
elseifos∈ ranvalueSetthen | ||
evalTermSet (valueSet⋅os) n | ||
elseifos∈ ranosWildthen | ||
evalTermWild (osWild⋅os) n | ||
else | ||
evalTermReference ec (valueRef⋅os) n | ||
evalValueType – returns pass if the supplied RDFTerm is:
evalValueType:IRI⇸RDFTerm⇸OptValidity | ||
∀ vt:IRI; n:RDFTerm; l:RDFLiteral • evalValueType vt n = | ||
ifvt = SHEX_IRI∧ n∈ ranirithenp | ||
elseifvt = SHEX_BNODE∧ n∈ ranbnodethenp | ||
elseifvt = SHEX_NONLITERAL∧ (n∈ raniri∨ n∈ ranbnode)thenp | ||
elseifvt = SHEX_LITERAL∧ n∈ ranliteralthenp | ||
elseifn∈ ranliteral∧ l = (literal⋅n)∧ | ||
((l∈ ranpl∧ (pl⋅l).dataType = vt)∨ | ||
(l∈ rantl∧ (tl⋅l).dataType = vt))thenp | ||
elsef | ||
evalTermSet – return p if the supplied RDFTerm is a member of MatchValue
evalTermSet:ℙMatchValue⇸RDFTerm⇸OptValidity | ||
∀ mvs:ℙMatchValue; n:RDFTerm • evalTermSet mvs n = | ||
if∃ mv:mvs • | ||
((mv∈ ranmviri∧ n∈ raniri∧ (iri⋅n) = mviri⋅mv)∨ | ||
(mv∈ ranmviris∧ n∈ raniri∧ | ||
(iri⋅n)∈ IRIstemRange (mviris⋅mv) )∨ | ||
(n∈ ranliteral∧ mvlit⋅mv = literal⋅n)) | ||
thenp | ||
elsef | ||
evalTermWild – return pass (p) if the supplied RDFTerm is not a member of MatchValue.
evalTermWild:ℙMatchValue→ RDFTerm→ OptValidity | ||
∀ mvs:ℙMatchValue; n:RDFTerm • evalTermWild mvs n = | ||
ifevalTermSet mvs n =pthenfelsep | ||
evalTermReference – return p if the subgraph of the EvalContext graph whose subjects match the supplied RDFTerm satisfies the ValueReference rule.
evalTermReference:EvalContext⇸Label⇸RDFTerm⇸OptValidity | ||
∀ ec:EvalContext; vr:Label; n:RDFTerm • | ||
evalTermReference ec vr n = | ||
ifn∉ ranliteralthenevalRule' ec n vr | ||
elsef | ||
The RevArcRule is used to select the subset of the graph having a given predicate or predicates and to determine whether the cardinality and/or “type” of this subset matches a supplied criteria. The rule itself consists of a PredicateFilter to select the triples, an SubjectSpecification to evaluate the result, a optional min and max cardinality and a (possibly empty) set of Actions:
RevArcRule | ||
filter:PredicateFilter | ||
valueSpec:SubjectSpecification | ||
min, max:optional[ℕ] | ||
actions:ℙAction | ||
(# min = 1∧ # max = 1)⇒ value min≤value max | ||
evalRevArcRule:EvalContext→ RDFTerm→ RevArcRule→ OptValidity | ||
∀ ec:EvalContext; o:RDFTerm; rar:RevArcRule; og:Graph | | ||
og = evalPredicateFilter rar.filter (triplesForObject o ec.graph) • | ||
evalRevArcRule ec o rar = | ||
ifevalCardinality og rar.min rar.max≠ p | ||
thenevalCardinality og rar.min rar.max | ||
elseifevalSubjectSpecification ec rar.valueSpec og≠ p | ||
thenevalSubjectSpecification ec rar.valueSpec og | ||
else | ||
dispatch rar.actions og ec | ||
SubjectSpecification specifies a set of possible values for an RDFTerm and takes one of the following forms:
SubjectSpecification ::= |
subjectSet《ℙMatchValue》| |
ssWild《ℙMatchValue》| |
subjectRef《Label》 |
paragraphevalSubjectSpecification – returns pass (p) if all of the triples in a Graph match the supplied SubjectSpecification, otherwise fail (f )
evalSubjectSpecification:EvalContext→ SubjectSpecification→ Graph→ | ||
OptValidity | ||
∀ ec:EvalContext; ss:SubjectSpecification; g:Graph • | ||
evalSubjectSpecification ec ss g = | ||
if∀ t:g • evalSubjectSpecificationTriple ec ss t.o =p | ||
thenp | ||
elsef | ||
evalSubjectSpecificationTriple:EvalContext→ SubjectSpecification→ | ||
RDFTerm→ OptValidity | ||
∀ ec:EvalContext; ss:SubjectSpecification; n:RDFTerm • | ||
evalSubjectSpecificationTriple ec ss n = | ||
ifss∈ ransubjectSetthen | ||
evalTermSet (subjectSet⋅ss) n | ||
elseifss∈ ranssWildthen | ||
evalTermWild (ssWild⋅ss) n | ||
else | ||
evalTermReference ec (subjectRef⋅ss) n | ||
A GroupRule serves two purposes. The first is to declare that a referenced rule is to be treated as “optional”, which, in this case means that if (a) the referenced rule returned none (∅), (meaning an ArcRule was encountered that had no matching predicates and a non-zero minimum cardinality) the group rule returns nomatch (z). An optional GroupRule also treats an error situation as a fail (f ).
The second purpose of a group rule is to allow a set of external actions to be evaluated whenever the referenced rule returns pass (p).
OPT ::= OPTIONAL | REQUIRED |
GroupRule≙[rule:Label; opt:OPT; actions:ℙAction ] |
evalGroupRule:EvalContext→ RDFTerm→ GroupRule→ OptValidity | ||
∀ ec:EvalContext; i:RDFTerm; gr:GroupRule • | ||
evalGroupRule ec i gr = | ||
ifevalRule' ec i gr.rule =∅∧ gr.opt = OPTIONAL | ||
thenz | ||
elseifevalRule' ec i gr.rule =ε∧ gr.opt = OPTIONAL | ||
thenf | ||
elseifevalRule' ec i gr.rule =p | ||
thendispatch gr.actions ∅ ec | ||
else | ||
evalRule' ec i gr.rule | ||
An AndRule consists of a set of one or more Rules, whose evaluation is determined by
the following table:
And | ∅ | z | f | p | ε |
---|---|---|---|---|---|
∅ | ∅1 | ∅1 | f1 | f1 | ε1 |
z | ∅1 | z1 | f1 | p1 | ε1 |
f | f1 | f1 | f1 | f1 | ε1 |
p | f1 | p1 | f1 | p1 | ε1 |
ε | ε1 | ε1 | ε1 | ε1 | ε1 |
The formal implementation of which will be realized in the corresponding function:
And:OptValidity→ OptValidity→ OptValidity | ||
Observing that the above table is a monoid with nomatch (z) as an identity element, evalAndRule can be applied using the standard functional pattern:
AndRule ==seq1Label |
evalAndRule:EvalContext→ RDFTerm→ AndRule→ OptValidity | ||
∀ ec:EvalContext; i:RDFTerm; r:AndRule • | ||
evalAndRule ec i r = | ||
foldr And z (map (evalRule' ec i) r) | ||
An XorRule consists of a set of one or more Rules, whose evaluation is determined by
the following table:
Or | ∅ | z | f | p | ε |
---|---|---|---|---|---|
∅ | ∅1 | z1 | ∅1 | p1 | ε1 |
z | z1 | z1 | z1 | p1 | ε1 |
f | ∅1 | z1 | f1 | p1 | ε1 |
p | p1 | p1 | p1 | ε23 | ε1 |
ε | ε1 | ε1 | ε1 | ε1 | ε1 |
Xor:OptValidity→ OptValidity→ OptValidity | ||
XorRule ==seq1Label |
evalXorRule:EvalContext→ RDFTerm→ XorRule→ OptValidity | ||
∀ ec:EvalContext; i:RDFTerm; r:XorRule • | ||
evalXorRule ec i r = | ||
foldr Xor f (map (evalRule' ec i) r) | ||
The dispatch function allows the evaluation / execution of arbitrary external “Actions”. While the evaluation of an Action can (obviously) have side effects outside the context of the ShEx environment, it must be side effect free within the execution context. In particular, an Action may not change anything in the EvalContext The action dispatcher exists to allow external events to happen. Parameters:
The dispatch function usually returns pass (p) or fail (f ), although there may also be cases for other OptValidity values in certain circumstances. The dispatch function always returns pass (p) if the set of actions is empty.
[Action] |
dispatch:ℙAction→ Graph→ EvalContext→ OptValidity | ||
∀ as:ℙAction; g:Graph; ec:EvalContext • | ||
as =∅⇒ dispatch as g ec =p | ||
The semantics of the productions and terminals from the Turtle specification are defined in Turtle Terse RDF Triple Language section 7 Parsing.
The following grammar rules are mapped to the abstract syntax:
Productions: | |||
[1] | ShExDoc |
::= | statement* |
[2] | statement |
::= | directive
| shape |
[3] | directive |
::= | sparqlPrefix
| sparqlBase
| "start" "=" ( label | typeSpec CODE* ) let b = a fresh blank node typeSpec.setLabel(b) new ArcRule() |
[4] | sparqlPrefix |
::= | "PREFIX" PNAME_NS IRIREF |
[5] | sparqlBase |
::= | "BASE" IRIREF |
[6] | shape |
::= | label typeSpec CODE* if (CODE.SIZE > 0) let r = new GroupRule(false, typeSpec) r.label = label else typeSpec.label = label |
[7] | typeSpec |
::= | "{" OrExpression "}" |
[8] | OrExpression |
::= | l:AndExpression ( "|" r:AndExpression )* if (r) new XorRule(l, r) else l |
[9] | AndExpression |
::= | l:UnaryExpression ( "," r:UnaryExpression )* if (r) new AndRule(l, r) else l |
[10] | UnaryExpression |
::= | arc |
| "(" OrExpression ")" opt:"?"? CODE* new GroupRule(OrExpression, opt, CODE) |
|||
[11] | label |
::= | iri
| BlankNode |
[12] | arc |
::= | nameClass valueSpec default? repeatCount? properties? CODE* new ArcRule(nameClass, valueSpec, default, repeatCount, properties, CODE) |
[13] | nameClass |
::= | iriStem pfIRI(iriStem) |
| "." exclusions pfWild(exclusions) |
|||
| 'a' pfIRI(rdf:type) |
|||
[14] | valueSpec |
::= | "@" label ValueReference(label) |
| typeSpec let b = a fresh blank node typeSpec.setLabel(b) |
|||
| valueSet new ValueSet(valueSet) |
|||
| object new ValueType(object) |
|||
| exclusions new ValueWild(exclusions) |
|||
[15] | iriStem |
::= | iri ("~")? |
[16] | default |
::= | "=" object |
[17] | properties |
::= | "[" iri object ( ";" ( iri object )? )* "]" |
[18] | exclusions |
::= | ( "-" iriStem )* |
[19] | repeatCount |
::= | "*"
| "+"
| "?"
| "{" INTEGER ( "," (INTEGER)? )? "}" |
[20] | valueSet |
::= | "(" (object)+ ")" |
[21] | object |
::= | iriStem
| BlankNode
| literal |
[22] | literal |
::= | RDFLiteral
| NumericLiteral
| BooleanLiteral |
[23] | NumericLiteral |
::= | INTEGER
| DECIMAL
| DOUBLE |
[24] | RDFLiteral |
::= | String ( LANGTAG | "^^" iri )? |
[25] | BooleanLiteral |
::= | "true"
| "false" |
[26] | String |
::= | STRING_LITERAL1
| STRING_LITERAL2
| STRING_LITERAL_LONG1
| STRING_LITERAL_LONG2 |
[27] | iri |
::= | IRIREF
| PrefixedName |
[28] | PrefixedName |
::= | PNAME_LN
| PNAME_NS |
[29] | BlankNode |
::= | BLANK_NODE_LABEL
| ANON |
Terminals Not in SPARQL: | |||
[30] | <CODE > |
::= | "%" ( [a-zA-Z+#_] ([a-zA-Z0-9+#_])* )? "{" ( [^%\\] | "\\" "%" )* "%" "}" |
A Shape Expressions schema with no semantic actions can be treated as unordered. In practice, error messages can be much clearer, and extension functions much simpler to write if the engine follows the lexical order when validating the members of a conjunction. Likewise, form and interface code generation will be more predictable and controllable if the Shape Expressions are processed in a specific order.
The foldr function is the standard functional pattern, which takes a binary function of type T, an identity function for type T, a sequence of type T and returns the result of applying the function to the right to left pairs of the sequence.
[T] | ||
foldr:(T→ T→ T)→ T→ seqT→ T | ||
∀ f:T→ T→ T; id:T; xs:seqT • | ||
foldr f id xs = | ||
ifxs =〈〉thenid | ||
elsef (head xs) (foldr f id (tail xs)) | ||
The map function takes a function from type A to type B and applies it to all members in the supplied sequence
[A,B] | ||
map:(A→ B)→ seqA→ seqB | ||
∀ f:A→ B; xs:seqA • | ||
map f xs = | ||
ifxs =〈〉then〈〉 | ||
else〈f (head xs)〉⌒map f (tail xs) | ||
Z uses the notion of free type definitions in the form:
FreeType ::= constructor《source》 |
constructor:source↣FreeType |
TravelDirections ::= |
bus《BusDirections》| |
walking《WalkingDirections》 |
x∈ TravelDirections |
ifx∈ ranbusthenbus⋅xelsewalking⋅x |
[X, Y] | ||
_⋅_:(X↣Y)× Y⇸X | ||
∀ f:X↣Y; y:Y • | ||
f⋅y = (μ x:domf | f x = y) | ||
One way to represent optional values is a set with one member. We take that route here and introduce a bit of syntactic sugar to show our intent:
optional[T] == { s:ℙT | # s≤1 } |
And a shorthand for addressing the content:
[T] | ||
value:ℙT⇸T | ||
∀ s:ℙT • value s = (μ e:T | e∈ s) | ||