Extract Elm values from Rdf.Graph'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 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.
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.parse
|> Result.withDefault Graph.empty
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 Blank Node or IRI.
import Rdf exposing (a)
import Rdf.Graph as Graph exposing (Graph)
graph : Graph
graph =
"""
@base <http://example.org/> .
<alice> <#knows> <bob> .
"""
|> Graph.parse
|> Result.withDefault Graph.empty
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 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.parse
|> Result.withDefault Graph.empty
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.parse
|> Result.withDefault Graph.empty
decode
(from
(Rdf.iri "http://example.org/alice")
(property (Rdf.iri "http://example.org/#isAdmin") bool)
)
graph
--> Ok TrueDecode 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.parse
|> Result.withDefault Graph.empty
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.parse
|> Result.withDefault Graph.empty
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.parse
|> Result.withDefault Graph.empty
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.parse
|> Result.withDefault Graph.empty
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.
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)Note that property a class alone 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.parse
|> Result.withDefault Graph.empty
decode
(from
(Rdf.iri "http://example.org/alice")
(property a (many iri))
)
graph
--> Ok
--> [ Rdf.iri "http://example.org/#Author"
--> , Rdf.iri "http://example.org/#Person"
--> ]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
collections 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.parse
|> Result.withDefault Graph.empty
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" ]
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.
Run a Decoder on an actual Graph starting at the provided
Node's.
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.
Transform the decoded value by applying the provided function.
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.
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.parse
|> Result.withDefault Graph.empty
type alias Person =
{ name : String
}
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.parse
|> Result.withDefault Graph.empty
type alias Person =
{ name : String
}
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.parse
|> Result.withDefault Graph.empty
type alias Person =
{ name : String
, admin : Bool
}
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
--> }
A way to specify what kind of thing you want to decode into.