hereon-mb/elm-rdf/1.1.1

NOTE: the latest version is 2.0.0

Rdf

This module defines the types and helper functions to work with the basic buildings blocks of the RDF ecosystem. If you are new to RDF, you should take a look at the RDF 1.1 Primer for a introduction on its data model.

type alias Triple =
{ subject : BlankNodeOrIri
, predicate : Iri
, object : BlankNodeOrIriOrLiteral
}

This type represents an RDF triple. It consists of

An RDF triple describes a directed labelled node within an RDF graph, pointing from the subject to the object and the label being the predicate.

type alias Term compatible =
Term compatible

This type represents an RDF Term (which can be an IRI, a literal, or a blank node), a query variable, or a property path. They are used in different contexts, for example when encoding or decoding RDF graphs, or when building different parts of a SPARQL query, like WHERE, CONSTRUCT, or SELECT clauses, as well as expressions.

The compatible type variable is used to ensure that certain instances of a Term can only be used in the right context. For example, subjects in an RDF graph can only be IRI's or blank nodes, or, verbs in a WHERE clause can only be IRI's, query variables or property paths.

For each term variant and all their combinations, we define two type aliases, one with a type variable and one without, e.g. IsIri compatible and Iri.

  • The first one will only be used for arguments of functions,
  • the second only for returned values.

Doing this makes the following code work, as the insert function uses the general Is... compatible types.

import Rdf.Graph as Graph exposing (Graph)


alice : Iri
alice =
    iri "http://example.org/alice"


knows : Iri
knows =
    iri "http://example.org/#knows"


someone : BlankNode
someone =
    blankNode "someone"


graph : Graph
graph =
    Graph.insert alice knows someone Graph.empty

Here is an overview of all possible terms and in which context they are allowed:

| Terms         | Graph | Where | Construct | Select | Expression | Path |
|               | S P O | S V O | S V O     |        |            |      |
|---------------|-------|-------|-----------|--------|------------|------|
| BlankNode     | x   x | x   x | x   x     |        |            |      |
| Iri           | x x x | x o x | x x x     |        |     x      |  o   |
| Literal       |     x |     x |     x     |        |     x      |      |
| Var           |       | x x x | x x x     |   x    |     x      |      |
| Path          |       |   x   |           |        |            |  x   |

It follows that a term can be compatible or not within the following combinations:

We consider an IRI to be the same as a predicate path and therefore define VarOrPath instead of IriOrVarOrPath.

Create

This section contains helper functions to create Term's from Elm values.

iri : String -> Iri

Create an IRI (Internal Resource Identifier) by providing its string representation, e.g.

alice : Iri
alice =
    iri "http://example.org/alice"
blankNode : String -> BlankNode

Create a blank node by providing a blank node identifier, e.g.

unnamed : BlankNode
unnamed =
    blankNode "unnamed"

Warning: When you are using this function directly, you have to ensure yourself, that you don't run into naming conflicts.

literal : Iri -> String -> Literal

Create a literal by providing its datatype IRI and its lexical form, e.g.

pi : Literal a
pi =
    literal xsdDecimal "3.14"


xsdDecimal : Iri
xsdDecimal =
    iri "http://www.w3.org/2001/XMLSchema#decimal"

There are a few helper functions for creating literals of the most common datatypes which are part of built-in datatypes.

varQ : String -> Var

Create a query variable of the form ?name.

varD : String -> Var

Create a query variable of the form $name.

inverse : IsPath compatible1 -> Path

Create an inverse property path.

sequence : IsPath compatible1 -> List (IsPath compatible2) -> Path

Create a sequence property path.

alternative : IsPath compatible1 -> List (IsPath compatible2) -> Path

Create an alternative property path.

zeroOrMore : IsPath compatible1 -> Path

Create a zero or more property path.

oneOrMore : IsPath compatible1 -> Path

Create a one or more property path.

zeroOrOne : IsPath compatible1 -> Path

Create a zero or one property path.

Specific literals

string : String -> Literal

Create a literal with datatype xsd:string.

string "Alice Wonderland"
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#string")
-->   "Alice Wonderland"
langString : String -> String -> Literal

Create a literal with datatype http://www.w3.org/1999/02/22-rdf-syntax-ns#langString. The first argument must be language tag as defined by BCP47, the second argument is the actual string.

serialize (langString "en" "RDF is great!")
--> "\"RDF is great!\"@en"
boolean : Bool -> Literal

Create a literal with datatype xsd:boolean.

boolean True
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#boolean")
-->   "true"

Numerical

decimal : Decimal -> Literal

Create a literal with datatype xsd:decimal. Here we are using the Decimal type from the torreyatcitty/the-best-decimal package.

import Decimal exposing (Decimal)


pi : Decimal
pi =
    3.14
        |> Decimal.fromFloat
        |> Maybe.withDefault (Decimal.fromInt 0)


decimal pi
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#decimal")
-->   "3.14"
integer : Int -> Literal

Create a literal with datatype xsd:integer.

integer 42
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#integer")
-->   "42"
int : Int -> Literal

Create a literal with datatype xsd:int.

int 42
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#int")
-->   "42"
double : Float -> Literal

Create a literal with datatype xsd:double.

double 3.14
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#double")
-->   "3.14"
float : Float -> Literal

Create a literal with datatype xsd:float.

float 3.14
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#float")
-->   "3.14"

Temporal

date : Posix -> Literal

Create a literal with datatype xsd:date.

import Time


date (Time.millisToPosix 0)
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#date")
-->   "1970-01-01"
dateTime : Posix -> Literal

Create a literal with datatype xsd:dateTime.

import Time


dateTime (Time.millisToPosix 0)
--> literal
-->   (iri "http://www.w3.org/2001/XMLSchema#dateTime")
-->   "1970-01-01T00:00:00.000Z"

Conversions

Specialize

This section contains helper functions to convert any Term's into a more specific variant.

toIri : Term compatible -> Maybe Iri

Turn any Term into an Iri if possible.

toBlankNode : Term compatible -> Maybe BlankNode

Turn any Term into a BlankNode if possible.

toLiteral : Term compatible -> Maybe Literal

Turn any Term into a Literal if possible.

toVar : Term compatible -> Maybe Var

Turn any Term into a Var if possible.

toBlankNodeOrIri : Term compatible -> Maybe BlankNodeOrIri

Turn any Term into a BlankNodeOrIri if possible.

toBlankNodeOrIriOrLiteral : Term compatible -> Maybe BlankNodeOrIriOrLiteral

Turn any Term into a BlankNodeOrIriOrLiteral if possible.

Elm values

This section contains helper functions to convert specific Term's into Elm values.

toUrl : Iri -> String

Extract the URL from an Iri.

toUrl (iri "http://example.org")
--> "http://example.org"
= Predicate Iri
| Inverse PropertyPath
| Sequence PropertyPath (List PropertyPath)
| Alternative PropertyPath (List PropertyPath)
| ZeroOrMore PropertyPath
| OneOrMore PropertyPath
| ZeroOrOne PropertyPath

A PropertyPath models the inner structure of a Path.

toPropertyPath : IsPath compatible -> PropertyPath

Turn a Path into a PropertyPath to work with its individual path segments.

toPropertyPath (iri "http://example.org")
--> Predicate (iri "http://example.org")


toPropertyPath (inverse (iri "http://example.org"))
--> Inverse (Predicate (iri "http://example.org"))
lexicalForm : Literal -> String

Turn Literal into it's lexical form.

lexicalForm (double 3.14)
--> "3.14"


lexicalForm (string "RDF is great!")
--> "RDF is great!"


lexicalForm (boolean True)
--> "true"
datatype : Literal -> Iri

Get the Literal's datatype as Iri.

datatype (string "Alice")
--> xsd "string"


datatype (langString "de" "Apfel")
--> rdf "langString"


datatype (integer 42)
--> xsd "integer"
toString : Term compatible -> Maybe String

Take any Term and extract its String value if it is a literal with datatype xsd:string.

toString (string "Alice")
--> Just "Alice"


toString (int 42)
--> Nothing
toLangString : Term compatible -> Maybe ( String, String )

Take any Term and extract its language tag and String value if it is a literal with datatype xsd:langString.

toLangString (langString "de" "Apfel")
--> Just ( "de", "Apfel" )


toLangString (int 42)
--> Nothing
toInt : Term compatible -> Maybe Int

Take any Term and extract its Int value if it is a literal with datatype xsd:integer or xsd:int.

toInt (integer 42)
--> Just 42


toInt (int 42)
--> Just 42


toInt (double 3.14)
--> Nothing
toFloat : Term compatible -> Maybe Float

Take any Term and extract its Float value if it is a literal with datatype xsd:double or xsd:float.

Rdf.toFloat (double 3.14)
--> Just 3.14


Rdf.toFloat (float 3.14)
--> Just 3.14


Rdf.toFloat (int 42)
--> Nothing
toDecimal : Term compatible -> Maybe Decimal

Take any Term and extract its Decimal value if it is a literal with datatype xsd:decimal.

import Decimal


toDecimal (decimal (Decimal.fromIntWithExponent 314 -2))
--> Just (Decimal.fromIntWithExponent 314 -2)


toDecimal (float 3.14)
--> Nothing


toDecimal (int 42)
--> Nothing
toDate : Term compatible -> Maybe Posix

Take any Term and extract its Posix value if it is a literal with datatype xsd:date.

toDateTime : Term compatible -> Maybe Posix

Take any Term and extract its Posix value if it is a literal with datatype xsd:dateTime.

toBool : Term compatible -> Maybe Bool

Take any Term and extract its Bool value if it is a literal with datatype xsd:boolean.

toBool (boolean True)
--> Just True

Transform IRI's

A few helper functions to transform Iri's.

appendPath : String -> IsIri compatible -> Iri

Append a String to the path component of an Iri.

appendPath "/alice" (iri "http://example.org")
--> iri "http://example.org/alice"


appendPath "/datasets" (iri "http://example.org?sort=id")
--> iri "http://example.org/datasets?sort=id"


appendPath "/people" (iri "http://example.org#alice")
--> iri "http://example.org/people#alice"
dropFragment : IsIri compatible -> Iri

Drop the fragment from an Iri.

dropFragment (iri "http://example.org#alice")
--> iri "http://example.org"
setFragment : String -> IsIri compatible -> Iri

Set the fragment of an Iri

setFragment "alice" (iri "http://example.org")
--> iri "http://example.org#alice"


setFragment "bob" (iri "http://example.org#alice")
--> iri "http://example.org#bob"
setQueryParam : String -> String -> IsIri compatible -> Iri

Set a query parameter in an Iri

setQueryParam "sort" "id" (iri "http://example.org")
--> iri "http://example.org?sort=id"


setQueryParam "sort" "name" (iri "http://example.org?sort=id")
--> iri "http://example.org?sort=name"

Transform query variables

append : String -> IsVar compatible -> IsVar compatible

Append a String to a query variable.

append "Label" (varQ "instance")
--> varQ "instanceLabel"




append "Label" (varD "instance")
--> varD "instanceLabel"

Property paths

startsWith : IsPath compatible1 -> IsPath compatible2 -> Bool

Check if the second property path starts with the first one.

startsWith
    (iri "http://example.org#knows")
    (sequence (iri "http://example.org#knows")
        [ rdfs "label" ]
    )
--> True


startsWith
    (iri "http://example.org#knows")
    (iri "http://example.org#knows")
--> True


startsWith
    (iri "http://example.org#knows")
    (iri "http://example.org#owns")
--> False
rightOf : IsPath compatible1 -> IsPath compatible2 -> Maybe Path

Return the property path which remains after removing the first path from the beginning of the second path. This will return Nothing if the second path does not start with the first, or if the resulting path is empty.

rightOf
    (iri "http://example.org#knows")
    (sequence (iri "http://example.org#knows")
        [ rdfs "label" ]
    )
--> Just (asPath (rdfs "label"))


rightOf
    (iri "http://example.org#knows")
    (iri "http://example.org#knows")
--> Nothing


rightOf
    (iri "http://example.org#knows")
    (iri "http://example.org#owns")
--> Nothing
lastPredicatePath : IsPath compatible -> Maybe Iri

Return the Iri from the last segment of the given property path.

lastPredicatePath
    (sequence (iri "http://example.org#knows")
        [ rdfs "label" ]
    )
--> Just (rdfs "label")

Serialization

serialize : Term compatible -> String

Serialize a Term into how it would be represented in the Turtle format or in SPARQL.

serializeWith : Prologue -> Term compatible -> String

Serialize a Term within the context of a Prologue.

type alias Prologue =
{ base : Maybe String
, prefixes : List ( String, String )
}

A Prologue captures the base and prefixes which are used to shorten the serialization of Term's.

serializeTriple : Triple -> String

Serialize a Triple into how it would be represented in the Turtle format or in SPARQL.

Helper

a : Iri

The IRI http://www.w3.org/1999/02/22-rdf-syntax-ns#type which is used to state that a node is an instance of an RDFS or OWL class.

Namespaces

A few helpers for commonly used IRI prefixes.

rdf : String -> Iri

The prefix http://www.w3.org/1999/02/22-rdf-syntax-ns#.

rdfs : String -> Iri

The prefix http://www.w3.org/2000/01/rdf-schema#.

xsd : String -> Iri

The prefix http://www.w3.org/2001/XMLSchema#.

owl : String -> Iri

The prefix http://www.w3.org/2002/07/owl#.

sh : String -> Iri

The prefix http://www.w3.org/ns/shacl#.

dcterms : String -> Iri

The prefix http://purl.org/dc/terms/.

prov : String -> Iri

The prefix http://www.w3.org/ns/prov#.

schema : String -> Iri

The prefix http://schema.org/.

Types

Basic

type alias Iri =
Term
{ iri : Compatible
, blankNodeOrIri : Compatible
, blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
, iriOrLiteralOrVar : Compatible
, iriOrVar : Compatible
, varOrPath : Compatible
, path : Compatible
}

An RDF term which can only be an IRI. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsIri compatible =
Term
{ compatible
| iri : Compatible
, blankNodeOrIri : Compatible
, blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
, iriOrLiteralOrVar : Compatible
, iriOrVar : Compatible
, varOrPath : Compatible
, path : Compatible
}

This type will only be used as the argument of functions and ensures that only IRI's are passed. Take a look at Term for a general explanation of the idea behind this.

asIri : IsIri compatible -> Iri

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

type alias BlankNode =
Term
{ blankNodeOrIri : Compatible
, blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
}

An RDF term which can only be a blank node. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsBlankNode compatible =
Term
{ compatible
| blankNodeOrIri : Compatible
, blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
}

This type will only be used as the argument of functions and ensures that only blank node's are passed. Take a look at Term for a general explanation of the idea behind this.

asBlankNode : IsBlankNode compatible -> BlankNode

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

type alias Literal =
Term
{ blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, iriOrLiteralOrVar : Compatible
}

An RDF term which can only be a literal. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsLiteral compatible =
Term
{ compatible
| blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, iriOrLiteralOrVar : Compatible
}

This type will only be used as the argument of functions and ensures that only literal's are passed. Take a look at Term for a general explanation of the idea behind this.

asLiteral : IsLiteral compatible -> Literal

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

type alias Var =
Term
{ isVar : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
, iriOrLiteralOrVar : Compatible
, iriOrVar : Compatible
, varOrPath : Compatible
}

An RDF term which can only be a query variable. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsVar compatible =
Term
{ compatible
| isVar : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
, iriOrLiteralOrVar : Compatible
, iriOrVar : Compatible
, varOrPath : Compatible
}

This type will only be used as the argument of functions and ensures that only query variable's are passed. Take a look at Term for a general explanation of the idea behind this.

asVar : IsVar compatible -> Var

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

type alias Path =
Term
{ varOrPath : Compatible
, path : Compatible
}

An RDF term which can only be a property path. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsPath compatible =
Term { compatible | varOrPath : Compatible, path : Compatible }

This type will only be used as the argument of functions and ensures that only property path's are passed. Take a look at Term for a general explanation of the idea behind this.

asPath : IsPath compatible -> Path

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

Combinations

type alias BlankNodeOrIri =
Term
{ blankNodeOrIri : Compatible
, blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
}

An RDF term which can only be a blank node or an IRI. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsBlankNodeOrIri compatible =
Term
{ compatible
| blankNodeOrIri : Compatible
, blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
}

This type will only be used as the argument of functions and ensures that only blank node's or IRI's are passed. Take a look at Term for a general explanation of the idea behind this.

asBlankNodeOrIri : IsBlankNodeOrIri compatible -> BlankNodeOrIri

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

Term
{ blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
}

An RDF term which can only be a blank node, an IRI, or a literal. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsBlankNodeOrIriOrLiteral compatible =
Term
{ compatible
| blankNodeOrIriOrLiteral : Compatible
, blankNodeOrIriOrLiteralOrVar : Compatible
}

This type will only be used as the argument of functions and ensures that only blank node's, IRI's, or literal's are passed. Take a look at Term for a general explanation of the idea behind this.

asBlankNodeOrIriOrLiteral : IsBlankNodeOrIriOrLiteral compatible -> BlankNodeOrIriOrLiteral

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

Term { blankNodeOrIriOrLiteralOrVar : Compatible }

An RDF term which can only be a blank node, an IRI, a literal, or a query variable. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsBlankNodeOrIriOrLiteralOrVar compatible =
Term { compatible | blankNodeOrIriOrLiteralOrVar : Compatible }

This type will only be used as the argument of functions and ensures that only blank node's, IRI's, literal's, or query variable's are passed. Take a look at Term for a general explanation of the idea behind this.

IsBlankNodeOrIriOrLiteralOrVar compatible
-> BlankNodeOrIriOrLiteralOrVar

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

type alias BlankNodeOrIriOrVar =
Term
{ blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
}

An RDF term which can only be a blank node, an IRI, or a query variable. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsBlankNodeOrIriOrVar compatible =
Term
{ compatible
| blankNodeOrIriOrLiteralOrVar : Compatible
, blankNodeOrIriOrVar : Compatible
}

This type will only be used as the argument of functions and ensures that only blank node's, IRI's, or query variable's are passed. Take a look at Term for a general explanation of the idea behind this.

asBlankNodeOrIriOrVar : IsBlankNodeOrIriOrVar compatible -> BlankNodeOrIriOrVar

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

type alias IriOrLiteralOrVar =
Term { iriOrLiteralOrVar : Compatible }

An RDF term which can only be an IRI, a literal, or a query variable. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsIriOrLiteralOrVar compatible =
Term { compatible | iriOrLiteralOrVar : Compatible }

This type will only be used as the argument of functions and ensures that only IRI's, literal's, or query variable's are passed. Take a look at Term for a general explanation of the idea behind this.

asIriOrLiteralOrVar : IsIriOrLiteralOrVar compatible -> IriOrLiteralOrVar

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

type alias VarOrPath =
Term { varOrPath : Compatible }

An RDF term which can only be a query variable or a property path. This type will only be used as the return type of functions and if the values need to be stored in the model. Take a look at Term for a general explanation of the idea behind this.

type alias IsVarOrPath compatible =
Term { compatible | varOrPath : Compatible }

This type will only be used as the argument of functions and ensures that only query variable's or property path's are passed. Take a look at Term for a general explanation of the idea behind this.

asVarOrPath : IsVarOrPath compatible -> VarOrPath

When writing your own helper functions, it might be necessary that you have to convert the argument type into the return value type. Take a look at Term for a general explanation of the idea behind this.

Utility

You can ignore this type, it is only used for implementing the different Term variants.