<?xml version="1.0" encoding="UTF-8"?>
<TEI xml:space="preserve" xmlns="http://www.tei-c.org/ns/1.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.tei-c.org/ns/1.0 https://raw.githubusercontent.com/kermitt2/grobid/master/grobid-home/schemas/xsd/Grobid.xsd"
 xmlns:xlink="http://www.w3.org/1999/xlink">
	<teiHeader xml:lang="en">
		<fileDesc>
			<titleStmt>
				<title level="a" type="main">Linking application and semantic data with RDF Lens</title>
			</titleStmt>
			<publicationStmt>
				<publisher/>
				<availability status="unknown"><licence/></availability>
			</publicationStmt>
			<sourceDesc>
				<biblStruct>
					<analytic>
						<author>
							<persName><forename type="first">Arthur</forename><surname>Vercruysse</surname></persName>
							<affiliation key="aff0">
								<orgName type="department">Department of Electronics and Information Systems</orgName>
								<orgName type="laboratory">IDLab</orgName>
								<orgName type="institution">Ghent University -imec</orgName>
							</affiliation>
						</author>
						<author>
							<persName><forename type="first">Julián</forename><surname>Rojas Meléndez</surname></persName>
							<affiliation key="aff0">
								<orgName type="department">Department of Electronics and Information Systems</orgName>
								<orgName type="laboratory">IDLab</orgName>
								<orgName type="institution">Ghent University -imec</orgName>
							</affiliation>
						</author>
						<author>
							<persName><forename type="first">Pieter</forename><surname>Colpaert</surname></persName>
							<affiliation key="aff0">
								<orgName type="department">Department of Electronics and Information Systems</orgName>
								<orgName type="laboratory">IDLab</orgName>
								<orgName type="institution">Ghent University -imec</orgName>
							</affiliation>
						</author>
						<title level="a" type="main">Linking application and semantic data with RDF Lens</title>
					</analytic>
					<monogr>
						<idno type="ISSN">1613-0073</idno>
					</monogr>
					<idno type="MD5">E86A3AD90B8CF87094D413BD3BB15A7B</idno>
				</biblStruct>
			</sourceDesc>
		</fileDesc>
		<encodingDesc>
			<appInfo>
				<application version="0.7.2" ident="GROBID" when="2025-04-23T18:46+0000">
					<desc>GROBID - A machine learning software for extracting information from scholarly documents</desc>
					<ref target="https://github.com/kermitt2/grobid"/>
				</application>
			</appInfo>
		</encodingDesc>
		<profileDesc>
			<textClass>
				<keywords>
					<term>RDF</term>
					<term>SHACL</term>
					<term>Functional programming</term>
					<term>Lenses</term>
					<term>JavaScript</term>
					<term>Haskell</term>
				</keywords>
			</textClass>
			<abstract>
<div xmlns="http://www.tei-c.org/ns/1.0"><p>Linked Data is commonly regarded as an unfriendly data structure to be directly used by application developers. The (often unknown) triple-based structure of RDF graphs causes developers to struggle to extract the triples of interest and translate them into the object-like structure needed for their application. A generic, composable and reusable way to look into RDF graphs as plain objects would remove an important barrier for integrating Linked Data in all facets of application logic. We propose RDF Lens, a library based on ideas from the Haskell lens library that allows for composable and reusable data extraction units, called lenses. Value is shown by implementing a lens that generates a new lens based on a SHACL shape that extracts the semantic data into the desired plain object. Abstracting data extraction at the lens level allows for mixed extraction: using both custom extraction and declarative extraction, which could increase ease of use and reusability. The current implementation is a proof of concept that defines how to extract data from an RDF graph in JavaScript applications but does not allow (yet) writing or altering linked data with the same lenses. Future work would allow for creating and updating Linked Data in the same elegant way.</p></div>
			</abstract>
		</profileDesc>
	</teiHeader>
	<text xml:lang="en">
		<body>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="1.">Introduction</head><p>When processing RDF data, a developer needs to deal with a list of interlinked triples that conform to a graph. The promise is that the added complexity of dealing with a graph can lead to higher interoperability as the IRIs used in named nodes in any position of the triple can be shared across datasets and systems. The contract between data and application code is loosened, as developers should not code against specific objects, but against graph patterns, allowing more systems to be connected.</p><p>Coding against such graph patterns is more complex than coding against structured data (e.g, JSON objects) and may require following non-traditional programming paradigms to build efficient and reusable code <ref type="bibr" target="#b0">[1]</ref>. While applications processing JSON-like objects already get the data in the right structure, applications processing RDF data need to write additional logic to create the structures they need to process data further. This arthur.vercruysse@ugent.be (A. Vercruysse); JulianAndres.RojasMelendez@UGent.be (J. R. Meléndez); pieter.colpaert@ugent.be (P. Colpaert) https://pietercolpaert.be (P. Colpaert) 0000-0003-3467-9755 (A. Vercruysse); 0000-0002-6645-1264 (J. R. Meléndez); 0000-0001-6917-2167 (P. Colpaert) becomes time-consuming and may lead to code duplication across the codebase, as similar logic might be needed for slightly different cases.</p><p>In the JavaScript ecosystem, libraries like Linked Data Objects <ref type="bibr" target="#b1">[2]</ref>, LDFlex <ref type="bibr" target="#b2">[3]</ref>, RDF Object<ref type="foot" target="#foot_0">1</ref> , or SimpleRDF<ref type="foot" target="#foot_1">2</ref> rely on JSON-LD contexts, which does not allow for typechecking on all object properties. Another type of library, ts-rdf-mapper<ref type="foot" target="#foot_2">3</ref> builds code that interacts with an RDF dataset based on annotations on the type definitions in the program itself. This approach is tightly coupled with the code base making it very difficult to reuse in different applications, compared to reusing the same JSON-LD context in multiple programs.</p><p>We aim to build a framework that allows to compose different pieces of data processing logic together, potentially reused from earlier tasks, to deliver the structures needed for an application. In that respect, the functional programming concept of data Lenses <ref type="bibr" target="#b3">[4]</ref>, as implemented in the Haskell lens library <ref type="foot" target="#foot_3">4</ref> , defines precisely such composable and reusable data structures. In Haskell, lenses are used to view, update or create (deeply) nested records. Without lenses, developers need to destructure entire objects and recompose them after each operation, similarly as it is needed when dealing with complex RDF graphs.</p><p>This paper shows how the idea of Haskell lenses can be applied to RDF. With lenses, extracting complex objects from a graph becomes easier due to the composability and typing support that lenses can provide. As the main use case, we show how to derive a new lens based on a SHACL shape, that in turn can extract objects according to the shape definition.</p><p>In the remainder of this paper, the second section provides a brief description of the Haskell lens concept. The third section shows how and why we apply the idea of lenses on RDF graphs. The next section describes the use case where we can derive a lens from a SHACL shape. The last section presents the conclusion and prospective future work.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.">Haskell lenses</head><p>In Haskell, working with structured data entails that for each modification on a nested value, a developer needs to destructure the object and reconstruct it back after performing the modification. This leads to unreadable and unmaintainable code. A Haskell lens aims to facilitate such procedures by lifting an operation over a value, to an operation over an object, also known as monads applied over data <ref type="bibr" target="#b4">[5]</ref>.</p><p>A lens is built by combining a getter and a setter function over a defined type. With a lens, is possible to perform operations over a data structure such as <ref type="bibr" target="#b5">[6]</ref>:</p><p>• Access a subpart (view) • Alter the whole by modifying a subpart (update) • Merge the lens with another lens to get a deeper view (composition) For example, take a data structure representing a Line type composed by a start and an end Point type. Increasing the x coordinate of the starting Point by one requires destructuring and reconstructing the entire Line object, as shown in Listing 1. In this example, a Point only has two coordinates, however, the code complexity increases quickly with more complex subtypes.</p><p>Lenses abstract how to access a nested object away and make it composable. Listing 1 also shows the same function implemented differently using lenses. The over function applies the (+1) after accessing the field and returns a modified object. That function is predefined in the Lens library, start and x are lenses generated by the library. Listing 1: Type declaration of a Line and a function that increases the x coordinate by one, implemented naively and with a Lens.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.">RDF Lens</head><p>RDF Lens<ref type="foot" target="#foot_4">5</ref> borrows the idea of a Haskell lens. A developer can look at the same graph with different lenses to see different data. This implementation only covers the get functionality: extracting the data and creating a new derived object. Often the starting type of an RDF lens is (𝐺, 𝑥) where 𝐺 = (𝑉, 𝐸) ∧ 𝐸 ⊆ {{𝑠, 𝑝, 𝑜}|𝑠, 𝑝, 𝑜 ∈ 𝑉 } ∧ 𝑥 ∈ 𝑉 (called Cont in code). RDF Lens includes some basic lenses that can be combined into more complex ones. The predicate lens (pred), for example, converts Cont into Array&lt;Cont&gt;, matching all objects after following that predicate, thus taking a step in the graph. Combining two of these predicate lenses and combining the result, creates a lens that can extract a typed object Point with an X and a Y coordinate (see Listing 2). The lenses are composable, Listing 2 shows that a lens that extracts a Line can be composed from Point lenses. Listing 2: A lens that extracts a Point, with an X and a Y coordinate from an RDF graph and a Lens that extracts a line from two points.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.">SHACL-based object extraction</head><p>To demonstrate the utility of RDF Lens, we implemented a lens that creates a lens from a SHACL shape <ref type="foot" target="#foot_5">6</ref> . We extract each defined property and interpret that property according to the sh:datatype or sh:class. If a sh:class is defined it will recursively apply a lens that corresponds to that class. The resulting lens results in a dictionary, each field name uses the value of sh:name. SHACL properties that define cardinality are also leveraged. sh:minCount determines if a field is required or not, and sh:maxCount dictates whether a single value or an array is to be expected. An example defining a Line can be seen at Listing 3.</p><p>With RDF Lens is possible to combine the SHACL-derived lenses with custom lenses. Listing 4 shows how to link a custom lens, with the undefined CBD class. In this case, the lens extracts the Concise Bounded Description (CBD)<ref type="foot" target="#foot_6">7</ref> set of triples, starting from the current term. This lens is provided by the RDF Lens library but is possible to combine externally defined lenses. Another predefined lens defined by RDF Lens, extracts a given SHACL Path and results in a lens itself.  Listing 3: A SHACL shape that defines a shape for a Line and a Point. This shape can be interpreted by RDF Lens to extract a Line from RDF data.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5.">Conclusion and future work</head><p>In this paper, we introduced RDF Lens as a developer tool to transform RDF triples into a structure that can be used by an application. The tool is available as an open-source library.</p><p>The idea that Haskell and RDF have a similar issue, resulted in the creation RDF lens (for the JavaScript ecosystem). So far, we limited the scope for this proof of concept to only extract objects from an RDF graph, and we do not allow yet for altering or generating RDF from objects. This already resulted in a promising tool, and these limitations will be addressed in future work. Listing 4: Javascript code example combining SHACL-derived and custom lenses.</p><p>As RDF Lens is already used today in our tooling to facilitate dealing directly with RDF data in JavaScript applications (both client-and server-side), we aim to support a broader adoption of it in the RDF developer community. We hope this will be the start of an ecosystem of reusable and composable RDF lenses.</p></div><figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_0"><head>SEMANTiCS' 24 :</head><label>24</label><figDesc>International Conference on Semantic Systems, September 17-19, 2024, Amsterdam, NL * Corresponding author.</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_1"><head>1 data 2 data 4 - 6 -</head><label>1246</label><figDesc>Point = Point { _x :: Double, _y :: Double } Line = Line { _start :: Point, _end :: Point } 3 -Deconstruct to access the values, return a reconstructed object 5 shiftStartByOne (Line (Point x y) end) = Line (Point (x + 1) y) end -`over`applies a function over a value after accessing the value using the lens 7 shiftStartByOne' = over (start . x) (+ 1)</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_2"><head>1 [ 4 [ 5 [</head><label>145</label><figDesc>sh:name 'x'; sh:path &lt;x&gt;; sh:datatype xsd:float; sh:maxCount 1 ], sh:name 'y'; sh:path &lt;y&gt;; sh:datatype xsd:float; sh:maxCount 1 ].</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_3"><head>[</head><label></label><figDesc>sh:name 'start'; sh:path &lt;start&gt;; sh:class &lt;Point&gt;; sh:maxCount 1 ],11[ sh:name 'end'; sh:path &lt;end&gt;; sh:class &lt;Point&gt;; sh:maxCount 1 ],[ sh:name 'quads'; sh:path (); sh:class &lt;CBD&gt;; sh:maxCount 1 ].</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_4"><head></head><label></label><figDesc>new Parser().parse(turtle); 9 const shapes = extractShapes(shapeQuads); 10 shapes.lenses["CBD"] = CBDLens; // Externally combined lens 11 12 const lens = shapes.lenses["Line"]; // The lens that extracts a line 13 const point = lens.execute({id: new NamedNode("MyPoint"), quads}); 14 15// { "start": {"x": 5, "y": 6}, "end": {"x": 0, "y": 7}, "quads": [/* &lt;6 quads&gt; */] }; 16 console.log(point);</figDesc></figure>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="1" xml:id="foot_0">https://github.com/rubensworks/rdf-object.js</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="2" xml:id="foot_1">https://github.com/simplerdf/simplerdf</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="3" xml:id="foot_2">https://github.com/artonio/ts-rdf-mapper</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="4" xml:id="foot_3">https://hackage.haskell.org/package/lens</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="5" xml:id="foot_4">The implementation is available under the MIT license on github (https://github.com/ajuvercr/rdf-lens).</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="6" xml:id="foot_5">The code is available in the repository: https://github.com/ajuvercr/rdf-lens/blob/master/src/shacl.ts</note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="7" xml:id="foot_6">https://www.w3.org/submissions/CBD</note>
		</body>
		<back>
			<div type="annex">
<div xmlns="http://www.tei-c.org/ns/1.0" />			</div>
			<div type="references">

				<listBibl>

<biblStruct xml:id="b0">
	<analytic>
		<title level="a" type="main">Programming the semantic web</title>
		<author>
			<persName><forename type="first">S</forename><surname>Staab</surname></persName>
		</author>
		<author>
			<persName><forename type="first">S</forename><surname>Scheglmann</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><surname>Leinberger</surname></persName>
		</author>
		<author>
			<persName><forename type="first">T</forename><surname>Gottron</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">The Semantic Web: Trends and Challenges</title>
				<meeting><address><addrLine>Cham</addrLine></address></meeting>
		<imprint>
			<publisher>Springer International Publishing</publisher>
			<date type="published" when="2014">2014</date>
			<biblScope unit="page" from="1" to="5" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b1">
	<analytic>
		<title level="a" type="main">Linked data objects (ldo): A typescript-enabled rdf devtool</title>
		<author>
			<persName><forename type="first">J</forename><surname>Morgan</surname></persName>
		</author>
		<idno type="DOI">10.1007/978-3-031-47243-5_13</idno>
	</analytic>
	<monogr>
		<title level="m">The Semantic Web -ISWC 2023: 22nd International Semantic Web Conference</title>
				<meeting><address><addrLine>Athens, Greece; Berlin, Heidelberg</addrLine></address></meeting>
		<imprint>
			<publisher>Springer-Verlag</publisher>
			<date type="published" when="2023">November 6-10, 2023. 2023</date>
			<biblScope unit="page" from="230" to="246" />
		</imprint>
	</monogr>
	<note>Proceedings, Part II</note>
</biblStruct>

<biblStruct xml:id="b2">
	<analytic>
		<title level="a" type="main">LDflex: a read/write Linked Data abstraction for front-end Web developers</title>
		<author>
			<persName><forename type="first">R</forename><surname>Verborgh</surname></persName>
		</author>
		<author>
			<persName><forename type="first">R</forename><surname>Taelman</surname></persName>
		</author>
		<idno type="DOI">10.1007/978-3-030-62466-8_13</idno>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 19th International Semantic Web Conference</title>
				<meeting>the 19th International Semantic Web Conference</meeting>
		<imprint>
			<date type="published" when="2020">2020</date>
			<biblScope unit="volume">12507</biblScope>
			<biblScope unit="page" from="193" to="211" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b3">
	<monogr>
		<title level="m" type="main">Haskell Design Patterns</title>
		<author>
			<persName><forename type="first">R</forename><surname>Lemmer</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2015">2015</date>
			<publisher>Packt Publishing Ltd</publisher>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b4">
	<analytic>
		<title level="a" type="main">Comprehending monads</title>
		<author>
			<persName><forename type="first">P</forename><surname>Wadler</surname></persName>
		</author>
		<idno type="DOI">10.1145/91556.91592</idno>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 1990 ACM Conference on LISP and Functional Programming, LFP &apos;90</title>
				<meeting>the 1990 ACM Conference on LISP and Functional Programming, LFP &apos;90</meeting>
		<imprint>
			<date type="published" when="1990">1990</date>
			<biblScope unit="page" from="61" to="78" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b5">
	<monogr>
		<author>
			<persName><forename type="first">S</forename><forename type="middle">L</forename><surname>Nita</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><surname>Mihailescu</surname></persName>
		</author>
		<idno type="DOI">10.1007/978-1-4842-4507-1_20</idno>
		<title level="m">Lens, Apress</title>
				<meeting><address><addrLine>Berkeley, CA</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2019">2019</date>
			<biblScope unit="page" from="145" to="151" />
		</imprint>
	</monogr>
</biblStruct>

				</listBibl>
			</div>
		</back>
	</text>
</TEI>
