Extract Elm values from Graph's and
Dataset's. This works similar to
Json.Decode
with a few differences:
You have to specify the node at which decoding starts. The reason is, that there is no obvious choice for this within a graph, like it is for a JSON object where decoding always starts at the root.
RDF allows multiple objects for one predicate, unlike JSON where a field is
assumed to appear once. Therefore one has to use many to switch
from decoding exactly one value to allowing arbitrarily many values
at a certain predicate.
When extracting values from an RDF Dataset, you have to select the correct (named/default) graph(s).
Decode an IRI.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> a <#Person> .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property a iri)
)
graph
--> Ok (Rdf.iri "http://example.org/#Person")Decode a blank node.
Decode a literal of any datatype.
Decode a term which is either a blank node or an IRI.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> <#knows> <bob> .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#knows") blankNodeOrIri)
)
graph
--> Ok (Rdf.asBlankNodeOrIri (Rdf.iri "http://example.org/bob"))Decode a term which is either a blank node, an IRI, or a literal.
Decode a Literal of type xsd:string into a String.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> <#name> "Alice Wonderland" .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#name") string)
)
graph
--> Ok "Alice Wonderland"Decode a literal of type rdf:langString into a ( String, String ) where
the first element is the language tag and the second the String value.
Decode a Literal of type xsd:boolean into a Bool.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> <#isAdmin> true .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#isAdmin") bool)
)
graph
--> Ok TrueDecode a literal of type xsd:decimal into a Decimal.
Decode a Literal of type xsd:integer or xsd:int into a Int.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<question> <#hasAnswer> 42 .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/question")
(property (Rdf.iri "http://example.org/#hasAnswer") int)
)
graph
--> Ok 42Decode a Literal of type xsd:double or xsd:float into a Float.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<question> <#hasAnswer> 314E-2 .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/question")
(property (Rdf.iri "http://example.org/#hasAnswer") float)
)
graph
--> Ok 3.14Decode a Literal of type xsd:integer, xsd:int, xsd:double, or
xsd:float into a Float.
Decode a Literal of type xsd:date into a Time.Posix.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
import Time
graph : Graph
graph =
"""
@base <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<alice> <#birthDate> "1970-01-01"^^xsd:date .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#birthDate") date)
)
graph
--> Ok (Time.millisToPosix 0)Decode a Literal of type xsd:date into a Time.Posix.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
import Time
graph : Graph
graph =
"""
@base <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<alice> <#birthTime> "1970-01-01T00:00:00"^^xsd:dateTime .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#birthTime") dateTime)
)
graph
--> Ok (Time.millisToPosix 0)Start decoding from the provided (focus) node. You can also nest this
Decoder in other Decoder's if you have to change the focus node.
Start decoding from all subjects. If the graph contains more then one
triple, you have to combine this with many to get a result.
Start decoding at each of the provided (focus) node. If more then one of
these nodes exist in your graph, you have to combine this with
many to get a result.
This type is used to distinguish the different graphs an RDF dataset is composed of.
When decoding a Dataset, run the decoder only inside the graphs specified
by the list of GraphIdentifier's.
When decoding a Dataset, run the decoder inside the union of all graphs
(default and named).
Decode a list of focus nodes by the given decoder.
Note that the position of many within a decode expression matters. Say,
a focus node has multiple classes. The following decoder works as expected:
property a (many class)However, the following (type-valid) decoder does not work:
many (property a class)The reason is that property a class fails (since there are many classes), and
so many (property a class) fails as a whole!
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> a <#Person> , <#Author> .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property a (many iri))
)
graph
--> Ok
--> [ Rdf.iri "http://example.org/#Person"
--> , Rdf.iri "http://example.org/#Author"
--> ]This is like many but you also get the index of the currently
decoded value. Note that the order in which nodes are decoded is
non-deterministic.
Try a bunch of different Decoder's. It will succeed with the first one
which succeeded. When all fail, you get the error for all cases.
Decode an RDF
collection into
a List.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> <#knows> (
<bob>
<cindi>
) .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#knows") (list iri))
)
graph
--> Ok [ Rdf.iri "http://example.org/bob", Rdf.iri "http://example.org/cindi" ]
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#knows") (many (list iri)))
)
graph
--> Ok [ [ Rdf.iri "http://example.org/bob", Rdf.iri "http://example.org/cindi" ] ]Run a decoder at the node which is obtained by following the provided
property path. Make sure to use many if more then one node can be
found, otherwise decoding will fail.
Run a decoder on the nodes which can be reached by any predicate from the
current focus node. Make sure to use many if more then one node can
be reached in this way.
This decoder succeeds if no nodes can be reached by following the provided property path.
Decode the list of all predicates for which the current focus node is the subject.
Use Rdf.Graph.decode or
Rdf.Dataset.decode to run a decoder on
a Graph or Dataset.
When the decoding fails, we get on of these. Use
errorToString to turn this into a human-friendly form.
The problem which made decoding fail.
Turn a decoding error into a human friendly string.
You can use this to mark that you are in a certain context. A stack of
these contexts will be provided with the Problem when
decoding fails, which you then can use to improve the reported error
message.
A decoder which always succeeds with the given value.
A decoder which always fails with the given message.
Transform the decoded value by applying the provided function.
A helper for combining Decoder's in a pipeline.
Run a Decoder and then run another one, where you can use the already
decoded value.
Turn a list of Decoder's into a Decoder of a list. This decoder will
fail whenever on of its elements fails.
Use this if you need to decode recursive data structures.
Decode a required property.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
import Time
graph : Graph
graph =
"""
@base <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<alice> <#knows> [ <#name> "Bob Builder" ] .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
type alias Person =
{ name : String
}
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(succeed Person
|> required
(Rdf.sequence
(Rdf.iri "http://example.org/#knows")
[ Rdf.iri "http://example.org/#name" ]
)
string
)
)
graph
--> Ok
--> { name = "Bob Builder"
--> }Decode an optional property.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
import Time
graph : Graph
graph =
"""
@base <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<alice> <#name> "Alice Wonderland" .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
type alias Person =
{ name : String
}
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(succeed Person
|> optional
(Rdf.sequence
(Rdf.iri "http://example.org/#knows")
[ Rdf.iri "http://example.org/#name" ]
)
string
"Unknown"
)
)
graph
--> Ok
--> { name = "Unknown"
--> }Rather than decoding anything, use a fixed value for the next step in the
pipeline. harcoded does not look at the RDF graph at all.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> <#name> "Alice Wonderland" .
"""
|> Graph.fromTurtle Rdf.initialSeed
|> Result.map Tuple.first
|> Result.withDefault Graph.empty
type alias Person =
{ name : String
, admin : Bool
}
Graph.decode
(from
(Rdf.iri "http://example.org/alice")
(succeed Person
|> required (Rdf.iri "http://example.org/#name") string
|> hardcoded True
)
)
graph
--> Ok
--> { name = "Alice Wonderland"
--> , admin = True
--> }Run the given decoder and feed its result into the pipeline at this point.
A way to specify what kind of type you want to decode into.