rdf4h 1.0.2 → 1.1.0
raw patch · 16 files changed
+677/−628 lines, 16 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.RDF: BNode :: !Text -> Node
- Data.RDF: BNodeGen :: !Int -> Node
- Data.RDF: BaseUrl :: Text -> BaseUrl
- Data.RDF: LNode :: !LValue -> Node
- Data.RDF: ParseFailure :: String -> ParseFailure
- Data.RDF: PlainL :: !Text -> LValue
- Data.RDF: PlainLL :: !Text -> !Text -> LValue
- Data.RDF: PrefixMapping :: (Text, Text) -> PrefixMapping
- Data.RDF: PrefixMappings :: (Map Text Text) -> PrefixMappings
- Data.RDF: Triple :: !Node -> !Node -> !Node -> Triple
- Data.RDF: TypedL :: !Text -> !Text -> LValue
- Data.RDF: UNode :: !Text -> Node
- Data.RDF: addPrefixMappings :: RDF rdf => rdf -> PrefixMappings -> Bool -> rdf
- Data.RDF: baseUrl :: RDF rdf => rdf -> Maybe BaseUrl
- Data.RDF: bnode :: Text -> Node
- Data.RDF: class RDF rdf
- Data.RDF: class RdfParser p
- Data.RDF: class RdfSerializer s
- Data.RDF: class View a b
- Data.RDF: data LValue
- Data.RDF: data Node
- Data.RDF: data Triple
- Data.RDF: empty :: RDF rdf => rdf
- Data.RDF: equalObjects :: Triple -> Triple -> Bool
- Data.RDF: equalPredicates :: Triple -> Triple -> Bool
- Data.RDF: equalSubjects :: Triple -> Triple -> Bool
- Data.RDF: fromEither :: RDF rdf => Either ParseFailure rdf -> rdf
- Data.RDF: hWriteH :: (RdfSerializer s, RDF rdf) => s -> Handle -> rdf -> IO ()
- Data.RDF: hWriteN :: RdfSerializer s => s -> Handle -> Node -> IO ()
- Data.RDF: hWriteRdf :: (RdfSerializer s, RDF rdf) => s -> Handle -> rdf -> IO ()
- Data.RDF: hWriteT :: RdfSerializer s => s -> Handle -> Triple -> IO ()
- Data.RDF: hWriteTs :: RdfSerializer s => s -> Handle -> Triples -> IO ()
- Data.RDF: instance Eq BaseUrl
- Data.RDF: instance Eq LValue
- Data.RDF: instance Eq Node
- Data.RDF: instance Eq ParseFailure
- Data.RDF: instance Eq Triple
- Data.RDF: instance Ord BaseUrl
- Data.RDF: instance Ord LValue
- Data.RDF: instance Ord Node
- Data.RDF: instance Ord Triple
- Data.RDF: instance Show BaseUrl
- Data.RDF: instance Show LValue
- Data.RDF: instance Show Node
- Data.RDF: instance Show ParseFailure
- Data.RDF: instance Show Triple
- Data.RDF: isBNode :: Node -> Bool
- Data.RDF: isEmpty :: RDF rdf => rdf -> Bool
- Data.RDF: isIsomorphic :: (RDF rdf1, RDF rdf2) => rdf1 -> rdf2 -> Bool
- Data.RDF: isLNode :: Node -> Bool
- Data.RDF: isUNode :: Node -> Bool
- Data.RDF: listObjectsOfPredicate :: RDF rdf => rdf -> Predicate -> [Object]
- Data.RDF: listSubjectsWithPredicate :: RDF rdf => rdf -> Predicate -> [Subject]
- Data.RDF: lnode :: LValue -> Node
- Data.RDF: mkRdf :: RDF rdf => Triples -> Maybe BaseUrl -> PrefixMappings -> rdf
- Data.RDF: newtype BaseUrl
- Data.RDF: newtype ParseFailure
- Data.RDF: newtype PrefixMapping
- Data.RDF: newtype PrefixMappings
- Data.RDF: objectOf :: Triple -> Node
- Data.RDF: parseFile :: (RdfParser p, RDF rdf) => p -> String -> IO (Either ParseFailure rdf)
- Data.RDF: parseString :: (RdfParser p, RDF rdf) => p -> Text -> Either ParseFailure rdf
- Data.RDF: parseURL :: (RdfParser p, RDF rdf) => p -> String -> IO (Either ParseFailure rdf)
- Data.RDF: plainL :: Text -> LValue
- Data.RDF: plainLL :: Text -> Text -> LValue
- Data.RDF: predicateOf :: Triple -> Node
- Data.RDF: prefixMappings :: RDF rdf => rdf -> PrefixMappings
- Data.RDF: query :: RDF rdf => rdf -> Maybe Node -> Maybe Node -> Maybe Node -> Triples
- Data.RDF: rdfContainsNode :: RDF rdf => rdf -> Node -> Bool
- Data.RDF: removeDupes :: Triples -> Triples
- Data.RDF: s2t :: String -> Text
- Data.RDF: select :: RDF rdf => rdf -> NodeSelector -> NodeSelector -> NodeSelector -> Triples
- Data.RDF: sortTriples :: Triples -> Triples
- Data.RDF: subjectOf :: Triple -> Node
- Data.RDF: t2s :: Text -> String
- Data.RDF: toPMList :: PrefixMappings -> [(Text, Text)]
- Data.RDF: triple :: Subject -> Predicate -> Object -> Triple
- Data.RDF: tripleContainsNode :: Node -> Triple -> Bool
- Data.RDF: triplesOf :: RDF rdf => rdf -> Triples
- Data.RDF: type NodeSelector = Maybe (Node -> Bool)
- Data.RDF: type Object = Node
- Data.RDF: type Predicate = Node
- Data.RDF: type Subject = Node
- Data.RDF: type Triples = [Triple]
- Data.RDF: typedL :: Text -> Text -> LValue
- Data.RDF: unode :: Text -> Node
- Data.RDF: view :: View a b => a -> b
- Data.RDF: writeH :: (RdfSerializer s, RDF rdf) => s -> rdf -> IO ()
- Data.RDF: writeN :: RdfSerializer s => s -> Node -> IO ()
- Data.RDF: writeRdf :: (RdfSerializer s, RDF rdf) => s -> rdf -> IO ()
- Data.RDF: writeT :: RdfSerializer s => s -> Triple -> IO ()
- Data.RDF: writeTs :: RdfSerializer s => s -> Triples -> IO ()
- Data.RDF.Namespace: instance Eq Namespace
- Data.RDF.Namespace: instance Eq PrefixMapping
- Data.RDF.Namespace: instance Eq PrefixMappings
- Data.RDF.Namespace: instance Ord PrefixMapping
- Data.RDF.Namespace: instance Ord PrefixMappings
- Data.RDF.Namespace: instance Show Namespace
- Data.RDF.Namespace: instance Show PrefixMapping
- Data.RDF.Namespace: instance Show PrefixMappings
+ Data.RDF.Query: equalObjects :: Triple -> Triple -> Bool
+ Data.RDF.Query: equalPredicates :: Triple -> Triple -> Bool
+ Data.RDF.Query: equalSubjects :: Triple -> Triple -> Bool
+ Data.RDF.Query: expandTriples :: RDF rdf => rdf -> Triples
+ Data.RDF.Query: fromEither :: RDF rdf => Either ParseFailure rdf -> rdf
+ Data.RDF.Query: isEmpty :: RDF rdf => rdf -> Bool
+ Data.RDF.Query: isIsomorphic :: (RDF rdf1, RDF rdf2) => rdf1 -> rdf2 -> Bool
+ Data.RDF.Query: listObjectsOfPredicate :: RDF rdf => rdf -> Predicate -> [Object]
+ Data.RDF.Query: listSubjectsWithPredicate :: RDF rdf => rdf -> Predicate -> [Subject]
+ Data.RDF.Query: objectOf :: Triple -> Node
+ Data.RDF.Query: predicateOf :: Triple -> Node
+ Data.RDF.Query: rdfContainsNode :: RDF rdf => rdf -> Node -> Bool
+ Data.RDF.Query: removeDupes :: Triples -> Triples
+ Data.RDF.Query: sortTriples :: Triples -> Triples
+ Data.RDF.Query: subjectOf :: Triple -> Node
+ Data.RDF.Query: tripleContainsNode :: Node -> Triple -> Bool
+ Data.RDF.Types: BNode :: !Text -> Node
+ Data.RDF.Types: BNodeGen :: !Int -> Node
+ Data.RDF.Types: BaseUrl :: Text -> BaseUrl
+ Data.RDF.Types: LNode :: !LValue -> Node
+ Data.RDF.Types: ParseFailure :: String -> ParseFailure
+ Data.RDF.Types: PlainL :: !Text -> LValue
+ Data.RDF.Types: PlainLL :: !Text -> !Text -> LValue
+ Data.RDF.Types: PlainNS :: Text -> Namespace
+ Data.RDF.Types: PrefixMapping :: (Text, Text) -> PrefixMapping
+ Data.RDF.Types: PrefixMappings :: (Map Text Text) -> PrefixMappings
+ Data.RDF.Types: PrefixedNS :: Text -> Text -> Namespace
+ Data.RDF.Types: Triple :: !Node -> !Node -> !Node -> Triple
+ Data.RDF.Types: TypedL :: !Text -> !Text -> LValue
+ Data.RDF.Types: UNode :: !Text -> Node
+ Data.RDF.Types: addPrefixMappings :: RDF rdf => rdf -> PrefixMappings -> Bool -> rdf
+ Data.RDF.Types: baseUrl :: RDF rdf => rdf -> Maybe BaseUrl
+ Data.RDF.Types: bnode :: Text -> Node
+ Data.RDF.Types: class RDF rdf
+ Data.RDF.Types: class RdfParser p
+ Data.RDF.Types: class RdfSerializer s
+ Data.RDF.Types: class View a b
+ Data.RDF.Types: data LValue
+ Data.RDF.Types: data Namespace
+ Data.RDF.Types: data Node
+ Data.RDF.Types: data Triple
+ Data.RDF.Types: empty :: RDF rdf => rdf
+ Data.RDF.Types: hWriteH :: (RdfSerializer s, RDF rdf) => s -> Handle -> rdf -> IO ()
+ Data.RDF.Types: hWriteN :: RdfSerializer s => s -> Handle -> Node -> IO ()
+ Data.RDF.Types: hWriteRdf :: (RdfSerializer s, RDF rdf) => s -> Handle -> rdf -> IO ()
+ Data.RDF.Types: hWriteT :: RdfSerializer s => s -> Handle -> Triple -> IO ()
+ Data.RDF.Types: hWriteTs :: RdfSerializer s => s -> Handle -> Triples -> IO ()
+ Data.RDF.Types: instance Eq BaseUrl
+ Data.RDF.Types: instance Eq LValue
+ Data.RDF.Types: instance Eq Namespace
+ Data.RDF.Types: instance Eq Node
+ Data.RDF.Types: instance Eq ParseFailure
+ Data.RDF.Types: instance Eq PrefixMapping
+ Data.RDF.Types: instance Eq PrefixMappings
+ Data.RDF.Types: instance Eq Triple
+ Data.RDF.Types: instance Ord BaseUrl
+ Data.RDF.Types: instance Ord LValue
+ Data.RDF.Types: instance Ord Node
+ Data.RDF.Types: instance Ord PrefixMapping
+ Data.RDF.Types: instance Ord PrefixMappings
+ Data.RDF.Types: instance Ord Triple
+ Data.RDF.Types: instance Show BaseUrl
+ Data.RDF.Types: instance Show LValue
+ Data.RDF.Types: instance Show Namespace
+ Data.RDF.Types: instance Show Node
+ Data.RDF.Types: instance Show ParseFailure
+ Data.RDF.Types: instance Show PrefixMapping
+ Data.RDF.Types: instance Show PrefixMappings
+ Data.RDF.Types: instance Show Triple
+ Data.RDF.Types: isBNode :: Node -> Bool
+ Data.RDF.Types: isLNode :: Node -> Bool
+ Data.RDF.Types: isUNode :: Node -> Bool
+ Data.RDF.Types: lnode :: LValue -> Node
+ Data.RDF.Types: mkRdf :: RDF rdf => Triples -> Maybe BaseUrl -> PrefixMappings -> rdf
+ Data.RDF.Types: newtype BaseUrl
+ Data.RDF.Types: newtype ParseFailure
+ Data.RDF.Types: newtype PrefixMapping
+ Data.RDF.Types: newtype PrefixMappings
+ Data.RDF.Types: parseFile :: (RdfParser p, RDF rdf) => p -> String -> IO (Either ParseFailure rdf)
+ Data.RDF.Types: parseString :: (RdfParser p, RDF rdf) => p -> Text -> Either ParseFailure rdf
+ Data.RDF.Types: parseURL :: (RdfParser p, RDF rdf) => p -> String -> IO (Either ParseFailure rdf)
+ Data.RDF.Types: plainL :: Text -> LValue
+ Data.RDF.Types: plainLL :: Text -> Text -> LValue
+ Data.RDF.Types: prefixMappings :: RDF rdf => rdf -> PrefixMappings
+ Data.RDF.Types: query :: RDF rdf => rdf -> Maybe Node -> Maybe Node -> Maybe Node -> Triples
+ Data.RDF.Types: select :: RDF rdf => rdf -> NodeSelector -> NodeSelector -> NodeSelector -> Triples
+ Data.RDF.Types: triple :: Subject -> Predicate -> Object -> Triple
+ Data.RDF.Types: triplesOf :: RDF rdf => rdf -> Triples
+ Data.RDF.Types: type NodeSelector = Maybe (Node -> Bool)
+ Data.RDF.Types: type Object = Node
+ Data.RDF.Types: type Predicate = Node
+ Data.RDF.Types: type Subject = Node
+ Data.RDF.Types: type Triples = [Triple]
+ Data.RDF.Types: typedL :: Text -> Text -> LValue
+ Data.RDF.Types: unode :: Text -> Node
+ Data.RDF.Types: view :: View a b => a -> b
+ Data.RDF.Types: writeH :: (RdfSerializer s, RDF rdf) => s -> rdf -> IO ()
+ Data.RDF.Types: writeN :: RdfSerializer s => s -> Node -> IO ()
+ Data.RDF.Types: writeRdf :: (RdfSerializer s, RDF rdf) => s -> rdf -> IO ()
+ Data.RDF.Types: writeT :: RdfSerializer s => s -> Triple -> IO ()
+ Data.RDF.Types: writeTs :: RdfSerializer s => s -> Triples -> IO ()
Files
- rdf4h.cabal +4/−2
- src/Data/RDF.hs +24/−538
- src/Data/RDF/MGraph.hs +2/−1
- src/Data/RDF/Namespace.hs +2/−33
- src/Data/RDF/Query.hs +118/−0
- src/Data/RDF/TriplesGraph.hs +2/−1
- src/Data/RDF/Types.hs +511/−0
- src/Data/RDF/Utils.hs +1/−40
- src/Rdf4hParseMain.hs +2/−3
- src/Text/RDF/RDF4H/Interact.hs +1/−1
- src/Text/RDF/RDF4H/NTriplesParser.hs +2/−4
- src/Text/RDF/RDF4H/NTriplesSerializer.hs +1/−1
- src/Text/RDF/RDF4H/ParserUtils.hs +1/−1
- src/Text/RDF/RDF4H/TurtleParser.hs +2/−1
- src/Text/RDF/RDF4H/TurtleSerializer.hs +2/−1
- src/Text/RDF/RDF4H/XmlParser.hs +2/−1
rdf4h.cabal view
@@ -1,5 +1,5 @@ name: rdf4h-version: 1.0.2+version: 1.1.0 synopsis: A library for RDF processing in Haskell description: 'RDF for Haskell' is a library for working with RDF in Haskell.@@ -19,7 +19,7 @@ build-type: Simple category: RDF stability: Experimental-tested-with: GHC==7.4.1+tested-with: GHC==7.6.1 extra-tmp-files: test flag small_base@@ -37,6 +37,8 @@ library exposed-modules: Data.RDF , Data.RDF.Namespace+ , Data.RDF.Types+ , Data.RDF.Query , Data.RDF.MGraph , Data.RDF.TriplesGraph , Text.RDF.RDF4H.TurtleParser
src/Data/RDF.hs view
@@ -1,545 +1,31 @@--- |The Core module provides the fundamental types,--- type classes, and functions of the library.------- TODO: update writeT to writeTriple, etc.+-- |The Core module exports all serializers and parsers,+-- types, and query functions of the library. module Data.RDF (- -- * Parsing RDF- RdfParser(parseString, parseFile, parseURL),- -- * Serializing RDF- RdfSerializer(hWriteRdf, writeRdf, hWriteH, writeH, hWriteTs, writeTs, hWriteT, writeT, hWriteN, writeN),- -- * RDF type- RDF(empty, mkRdf, triplesOf, select, query, baseUrl, prefixMappings, addPrefixMappings),- -- * RDF triples, nodes, and literals- Triple(Triple), triple, Triples, sortTriples,- Node(UNode, BNode, BNodeGen, LNode),- LValue(PlainL, PlainLL, TypedL), - -- * Supporting types and functions- BaseUrl(BaseUrl),- PrefixMappings(PrefixMappings), toPMList, PrefixMapping(PrefixMapping),- NodeSelector, isUNode, isBNode, isLNode,- equalSubjects, equalPredicates, equalObjects,- isIsomorphic,- subjectOf, predicateOf, objectOf, isEmpty,- rdfContainsNode,tripleContainsNode,- listSubjectsWithPredicate,listObjectsOfPredicate,- Subject, Predicate, Object,- ParseFailure(ParseFailure),- {- FastString(uniq,value),mkFastString, -}- s2t,t2s,unode,bnode,lnode,plainL,plainLL,typedL,- View, view,- fromEither, removeDupes-)-where--import Data.RDF.Namespace-import Data.RDF.Utils ( s2t, t2s, canonicalize )-import qualified Data.Text as T-import Data.List-import System.IO-import Text.Printf---- |A type class for ADTs that expose views to clients.-class View a b where- view :: a -> b---- |An alias for 'Node', defined for convenience and readability purposes.-type Subject = Node---- |An alias for 'Node', defined for convenience and readability purposes.-type Predicate = Node---- |An alias for 'Node', defined for convenience and readability purposes.-type Object = Node---- |An RDF value is a set of (unique) RDF triples, together with the--- operations defined upon them.------ For information about the efficiency of the functions, see the--- documentation for the particular RDF instance.------ For more information about the concept of an RDF graph, see--- the following: <http://www.w3.org/TR/rdf-concepts/#section-rdf-graph>.-class RDF rdf where-- -- |Return the base URL of this RDF, if any.- baseUrl :: rdf -> Maybe BaseUrl-- -- |Return the prefix mappings defined for this RDF, if any.- prefixMappings :: rdf -> PrefixMappings-- -- |Return an RDF with the specified prefix mappings merged with- -- the existing mappings. If the Bool arg is True, then a new mapping- -- for an existing prefix will replace the old mapping; otherwise,- -- the new mapping is ignored.- addPrefixMappings :: rdf -> PrefixMappings -> Bool -> rdf-- -- |Return an empty RDF.- empty :: rdf-- -- |Return a RDF containing all the given triples. Handling of duplicates- -- in the input depend on the particular RDF implementation.- mkRdf :: Triples -> Maybe BaseUrl -> PrefixMappings -> rdf-- -- |Return all triples in the RDF, as a list.- triplesOf :: rdf -> Triples-- -- |Select the triples in the RDF that match the given selectors.- --- -- The three NodeSelector parameters are optional functions that match- -- the respective subject, predicate, and object of a triple. The triples- -- returned are those in the given graph for which the first selector- -- returns true when called on the subject, the second selector returns- -- true when called on the predicate, and the third selector returns true- -- when called on the ojbect. A 'Nothing' parameter is equivalent to a- -- function that always returns true for the appropriate node; but- -- implementations may be able to much more efficiently answer a select- -- that involves a 'Nothing' parameter rather than an @(id True)@ parameter.- --- -- The following call illustrates the use of select, and would result in- -- the selection of all and only the triples that have a blank node- -- as subject and a literal node as object:- --- -- > select gr (Just isBNode) Nothing (Just isLNode)- --- -- Note: this function may be very slow; see the documentation for the- -- particular RDF implementation for more information.- select :: rdf -> NodeSelector -> NodeSelector -> NodeSelector -> Triples-- -- |Return the triples in the RDF that match the given pattern, where- -- the pattern (3 Maybe Node parameters) is interpreted as a triple pattern.- --- -- The @Maybe Node@ params are interpreted as the subject, predicate, and- -- object of a triple, respectively. @Just n@ is true iff the triple has- -- a node equal to @n@ in the appropriate location; @Nothing@ is always- -- true, regardless of the node in the appropriate location.- --- -- For example, @ query rdf (Just n1) Nothing (Just n2) @ would return all- -- and only the triples that have @n1@ as subject and @n2@ as object,- -- regardless of the predicate of the triple.- query :: rdf -> Maybe Node -> Maybe Node -> Maybe Node -> Triples---- |An RdfParser is a parser that knows how to parse 1 format of RDF and--- can parse an RDF document of that type from a string, a file, or a URL.--- Required configuration options will vary from instance to instance.-class RdfParser p where-- -- |Parse RDF from the given bytestring, yielding a failure with error message or- -- the resultant RDF.- parseString :: forall rdf. (RDF rdf) => p -> T.Text -> Either ParseFailure rdf-- -- |Parse RDF from the local file with the given path, yielding a failure with error- -- message or the resultant RDF in the IO monad.- parseFile :: forall rdf. (RDF rdf) => p -> String -> IO (Either ParseFailure rdf)-- -- |Parse RDF from the remote file with the given HTTP URL (https is not supported),- -- yielding a failure with error message or the resultant graph in the IO monad.- parseURL :: forall rdf. (RDF rdf) => p -> String -> IO (Either ParseFailure rdf)---- |An RdfSerializer is a serializer of RDF to some particular output format, such as--- NTriples or Turtle.-class RdfSerializer s where- -- |Write the RDF to a file handle using whatever configuration is specified by- -- the first argument.- hWriteRdf :: forall rdf. (RDF rdf) => s -> Handle -> rdf -> IO ()-- -- |Write the RDF to stdout; equivalent to @'hWriteRdf' stdout@.- writeRdf :: forall rdf. (RDF rdf) => s -> rdf -> IO ()-- -- |Write to the file handle whatever header information is required based on- -- the output format. For example, if serializing to Turtle, this method would- -- write the necessary \@prefix declarations and possibly a \@baseUrl declaration,- -- whereas for NTriples, there is no header section at all, so this would be a no-op.- hWriteH :: forall rdf. (RDF rdf) => s -> Handle -> rdf -> IO ()-- -- |Write header information to stdout; equivalent to @'hWriteRdf' stdout@.- writeH :: forall rdf. (RDF rdf) => s -> rdf -> IO ()-- -- |Write some triples to a file handle using whatever configuration is specified- -- by the first argument. - -- - -- WARNING: if the serialization format has header-level information - -- that should be output (e.g., \@prefix declarations for Turtle), then you should- -- use 'hWriteG' instead of this method unless you're sure this is safe to use, since- -- otherwise the resultant document will be missing the header information and - -- will not be valid.- hWriteTs :: s -> Handle -> Triples -> IO ()-- -- |Write some triples to stdout; equivalent to @'hWriteTs' stdout@.- writeTs :: s -> Triples -> IO ()-- -- |Write a single triple to the file handle using whatever configuration is - -- specified by the first argument. The same WARNING applies as to 'hWriteTs'.- hWriteT :: s -> Handle -> Triple -> IO ()-- -- |Write a single triple to stdout; equivalent to @'hWriteT' stdout@.- writeT :: s -> Triple -> IO ()-- -- |Write a single node to the file handle using whatever configuration is - -- specified by the first argument. The same WARNING applies as to 'hWriteTs'.- hWriteN :: s -> Handle -> Node -> IO ()-- -- |Write a single node to sdout; equivalent to @'hWriteN' stdout@.- writeN :: s -> Node -> IO ()---- |An RDF node, which may be either a URIRef node ('UNode'), a blank--- node ('BNode'), or a literal node ('LNode').-data Node =-- -- |An RDF URI reference. See- -- <http://www.w3.org/TR/rdf-concepts/#section-Graph-URIref> for more- -- information.- UNode !T.Text-- -- |An RDF blank node. See- -- <http://www.w3.org/TR/rdf-concepts/#section-blank-nodes> for more- -- information.- | BNode !T.Text-- -- |An RDF blank node with an auto-generated identifier, as used in- -- Turtle.- | BNodeGen !Int-- -- |An RDF literal. See- -- <http://www.w3.org/TR/rdf-concepts/#section-Graph-Literal> for more- -- information.- | LNode !LValue---- ==============================--- Constructor functions for Node---- |Return a URIRef node for the given bytetring URI.-{-# INLINE unode #-}-unode :: T.Text -> Node-unode = UNode---- |Return a blank node using the given string identifier.-{-# INLINE bnode #-}-bnode :: T.Text -> Node-bnode = BNode---- |Return a literal node using the given LValue.-{-# INLINE lnode #-}-lnode :: LValue -> Node-lnode = LNode---- Constructor functions for Node--- ==============================----- |A list of triples. This is defined for convenience and readability.-type Triples = [Triple]---- |An RDF triple is a statement consisting of a subject, predicate,--- and object, respectively.------ See <http://www.w3.org/TR/rdf-concepts/#section-triples> for--- more information.-data Triple = Triple !Node !Node !Node---- |A smart constructor function for 'Triple' that verifies the node arguments--- are of the correct type and creates the new 'Triple' if so or calls 'error'.--- /subj/ must be a 'UNode' or 'BNode', and /pred/ must be a 'UNode'.-triple :: Subject -> Predicate -> Object -> Triple-triple subj pred obj- | isLNode subj = error $ "subject must be UNode or BNode: " ++ show subj- | isLNode pred = error $ "predicate must be UNode, not LNode: " ++ show pred- | isBNode pred = error $ "predicate must be UNode, not BNode: " ++ show pred- | otherwise = Triple subj pred obj---- |The actual value of an RDF literal, represented as the 'LValue'--- parameter of an 'LNode'.-data LValue =- -- Constructors are not exported, because we need to have more- -- control over the format of the literal bytestring that we store.-- -- |A plain (untyped) literal value in an unspecified language.- PlainL !T.Text-- -- |A plain (untyped) literal value with a language specifier.- | PlainLL !T.Text !T.Text-- -- |A typed literal value consisting of the literal value and- -- the URI of the datatype of the value, respectively.- | TypedL !T.Text !T.Text---- ================================--- Constructor functions for LValue---- |Return a PlainL LValue for the given string value.-{-# INLINE plainL #-}-plainL :: T.Text -> LValue-plainL = PlainL---- |Return a PlainLL LValue for the given string value and language,--- respectively.-{-# INLINE plainLL #-}-plainLL :: T.Text -> T.Text -> LValue-plainLL = PlainLL---- |Return a TypedL LValue for the given string value and datatype URI,--- respectively.-{-# INLINE typedL #-}-typedL :: T.Text -> T.Text -> LValue-typedL val dtype = TypedL (canonicalize dtype val) dtype---- Constructor functions for LValue--- ================================----- |The base URL of an RDF.-newtype BaseUrl = BaseUrl T.Text- deriving (Eq, Ord, Show)---- |A 'NodeSelector' is either a function that returns 'True'--- or 'False' for a node, or Nothing, which indicates that all--- nodes would return 'True'.------ The selector is said to select, or match, the nodes for--- which it returns 'True'.------ When used in conjunction with the 'select' method of 'Graph', three--- node selectors are used to match a triple.-type NodeSelector = Maybe (Node -> Bool)---- |Represents a failure in parsing an N-Triples document, including--- an error message with information about the cause for the failure.-newtype ParseFailure = ParseFailure String- deriving (Eq, Show)---- |A node is equal to another node if they are both the same type--- of node and if the field values are equal.-instance Eq Node where- (UNode bs1) == (UNode bs2) = bs1 == bs2- (BNode bs1) == (BNode bs2) = bs1 == bs2- (BNodeGen i1) == (BNodeGen i2) = i1 == i2- (LNode l1) == (LNode l2) = l1 == l2- _ == _ = False---- |Node ordering is defined first by type, with Unode < BNode < BNodeGen--- < LNode PlainL < LNode PlainLL < LNode TypedL, and secondly by--- the natural ordering of the node value.------ E.g., a '(UNode _)' is LT any other type of node, and a--- '(LNode (TypedL _ _))' is GT any other type of node, and the ordering--- of '(BNodeGen 44)' and '(BNodeGen 3)' is that of the values, or--- 'compare 44 3', GT.-instance Ord Node where- compare = compareNode--compareNode :: Node -> Node -> Ordering-compareNode (UNode bs1) (UNode bs2) = compare bs1 bs2-compareNode (UNode _) _ = LT-compareNode (BNode bs1) (BNode bs2) = compare bs1 bs2-compareNode (BNode _) (UNode _) = GT-compareNode (BNode _) _ = LT-compareNode (BNodeGen i1) (BNodeGen i2) = compare i1 i2-compareNode (BNodeGen _) (LNode _) = LT-compareNode (BNodeGen _) _ = GT-compareNode (LNode (PlainL bs1)) (LNode (PlainL bs2)) = compare bs1 bs2-compareNode (LNode (PlainL _)) (LNode _) = LT-compareNode (LNode (PlainLL bs1 bs1')) (LNode (PlainLL bs2 bs2')) =- case compare bs1' bs2' of- EQ -> compare bs1 bs2- LT -> LT- GT -> GT-compareNode (LNode (PlainLL _ _)) (LNode (PlainL _)) = GT-compareNode (LNode (PlainLL _ _)) (LNode _) = LT-compareNode (LNode (TypedL bsType1 bs1)) (LNode (TypedL bsType2 bs2)) =- case compare bs1 bs2 of- EQ -> compare bsType1 bsType2- LT -> LT- GT -> GT-compareNode (LNode (TypedL _ _)) (LNode _) = GT-compareNode (LNode _) _ = GT---- |Two triples are equal iff their respective subjects, predicates, and objects--- are equal.-instance Eq Triple where- (Triple s1 p1 o1) == (Triple s2 p2 o2) = s1 == s2 && p1 == p2 && o1 == o2---- |The ordering of triples is based on that of the subject, predicate, and object--- of the triple, in that order.-instance Ord Triple where- (Triple s1 p1 o1) `compare` (Triple s2 p2 o2) =- case compareNode s1 s2 of- EQ -> case compareNode p1 p2 of- EQ -> compareNode o1 o2- LT -> LT- GT -> GT- GT -> GT- LT -> LT---- |Two 'LValue' values are equal iff they are of the same type and all fields are--- equal.-instance Eq LValue where- (PlainL bs1) == (PlainL bs2) = bs1 == bs2- (PlainLL bs1 bs1') == (PlainLL bs2 bs2') = bs1' == bs2' && bs1 == bs2- (TypedL bsType1 bs1) == (TypedL bsType2 bs2) = bsType1 == bsType2 && bs1 == bs2- _ == _ = False---- |Ordering of 'LValue' values is as follows: (PlainL _) < (PlainLL _ _)--- < (TypedL _ _), and values of the same type are ordered by field values,--- with '(PlainLL literalValue language)' being ordered by language first and--- literal value second, and '(TypedL literalValue datatypeUri)' being ordered--- by datatype first and literal value second.-instance Ord LValue where- compare = compareLValue--{-# INLINE compareLValue #-}-compareLValue :: LValue -> LValue -> Ordering-compareLValue (PlainL bs1) (PlainL bs2) = compare bs1 bs2-compareLValue (PlainL _) _ = LT-compareLValue _ (PlainL _) = GT-compareLValue (PlainLL bs1 bs1') (PlainLL bs2 bs2') =- case compare bs1' bs2' of- EQ -> compare bs1 bs2- GT -> GT- LT -> LT-compareLValue (PlainLL _ _) _ = LT-compareLValue _ (PlainLL _ _) = GT-compareLValue (TypedL l1 t1) (TypedL l2 t2) =- case compare t1 t2 of- EQ -> compare l1 l2- GT -> GT- LT -> LT---- String representations of the various data types; generally NTriples-like.--instance Show Triple where- show (Triple s p o) =- printf "Triple(%s,%s,%s)" (show s) (show p) (show o)--instance Show Node where- show (UNode uri) = "UNode(" ++ show uri ++ ")"- show (BNode i) = "BNode(" ++ show i ++ ")"- show (BNodeGen genId) = "BNodeGen(" ++ show genId ++ ")"- show (LNode lvalue) = "LNode(" ++ show lvalue ++ ")"--instance Show LValue where- show (PlainL lit) = "PlainL(" ++ T.unpack lit ++ ")"- show (PlainLL lit lang) = "PlainLL(" ++ T.unpack lit ++ ", " ++ T.unpack lang ++ ")"- show (TypedL lit dtype) = "TypedL(" ++ T.unpack lit ++ "," ++ show dtype ++ ")"---- |Answer the given list of triples in sorted order.-sortTriples :: Triples -> Triples-sortTriples = sort---- |Answer the subject node of the triple.-{-# INLINE subjectOf #-}-subjectOf :: Triple -> Node-subjectOf (Triple s _ _) = s---- |Answer the predicate node of the triple.-{-# INLINE predicateOf #-}-predicateOf :: Triple -> Node-predicateOf (Triple _ p _) = p---- |Answer the object node of the triple.-{-# INLINE objectOf #-}-objectOf :: Triple -> Node-objectOf (Triple _ _ o) = o---- |Answer if rdf contains node.-rdfContainsNode :: forall rdf. (RDF rdf) => rdf -> Node -> Bool-rdfContainsNode rdf node =- let ts = triplesOf rdf- xs = map (tripleContainsNode node) ts- in elem True xs---- |Answer if triple contains node.-tripleContainsNode :: Node -> Triple -> Bool-{-# INLINE tripleContainsNode #-}-tripleContainsNode node t = - subjectOf t == node || predicateOf t == node || objectOf t == node---- |Answer if given node is a URI Ref node.-{-# INLINE isUNode #-}-isUNode :: Node -> Bool-isUNode (UNode _) = True-isUNode _ = False---- |Answer if given node is a blank node.-{-# INLINE isBNode #-}-isBNode :: Node -> Bool-isBNode (BNode _) = True-isBNode (BNodeGen _) = True-isBNode _ = False---- |Answer if given node is a literal node.-{-# INLINE isLNode #-}-isLNode :: Node -> Bool-isLNode (LNode _) = True-isLNode _ = False---- |Determine whether two triples have equal subjects.-equalSubjects :: Triple -> Triple -> Bool-equalSubjects (Triple s1 _ _) (Triple s2 _ _) = s1 == s2---- |Determine whether two triples have equal predicates.-equalPredicates :: Triple -> Triple -> Bool-equalPredicates (Triple _ p1 _) (Triple _ p2 _) = p1 == p2---- |Determine whether two triples have equal objects.-equalObjects :: Triple -> Triple -> Bool-equalObjects (Triple _ _ o1) (Triple _ _ o2) = o1 == o2---- |Determines whether the 'RDF' contains zero triples.-isEmpty :: RDF rdf => rdf -> Bool-isEmpty rdf =- let ts = triplesOf rdf- in null ts---- |Lists of all subjects of triples with the given predicate.-listSubjectsWithPredicate :: RDF rdf => rdf -> Predicate -> [Subject]-listSubjectsWithPredicate rdf pred =- listNodesWithPredicate rdf pred subjectOf---- |Lists of all objects of triples with the given predicate.-listObjectsOfPredicate :: RDF rdf => rdf -> Predicate -> [Object]-listObjectsOfPredicate rdf pred =- listNodesWithPredicate rdf pred objectOf--listNodesWithPredicate :: RDF rdf => rdf -> Predicate -> (Triple -> Node) -> [Node]-listNodesWithPredicate rdf pred f =- let ts = triplesOf rdf- xs = filter (\t -> predicateOf t == pred) ts- in map f xs----- |Convert a parse result into an RDF if it was successful--- and error and terminate if not.-fromEither :: RDF rdf => Either ParseFailure rdf -> rdf-fromEither res =- case res of- (Left err) -> error (show err)- (Right rdf) -> rdf+ -- * Export types and query functions+ module Data.RDF.Types,+ module Data.RDF.Query, --- |Remove duplicate triples, returning unique triples. This --- function may return the triples in a different order than --- given.-removeDupes :: Triples -> Triples-removeDupes = map head . group . sort+ -- * Export RDF type class instances+ module Data.RDF.TriplesGraph,+ module Data.RDF.MGraph, --- |This determines if two RDF representations are equal regardless of blank--- node names, triple order and prefixes. In math terms, this is the \simeq--- latex operator, or ~=-isIsomorphic :: forall rdf1 rdf2. (RDF rdf1, RDF rdf2) => rdf1 -> rdf2 -> Bool-isIsomorphic g1 g2 = normalize g1 == normalize g2- where normalize :: forall rdf. (RDF rdf) => rdf -> Triples- normalize = sort . nub . expandTriples+ -- * Export RDF parsers and serializers+ module Text.RDF.RDF4H.NTriplesSerializer,+ module Text.RDF.RDF4H.NTriplesParser,+ module Text.RDF.RDF4H.TurtleSerializer,+ module Text.RDF.RDF4H.TurtleParser, --- |Expand the triples in a graph with the prefix map and base URL for that--- graph.-expandTriples :: (RDF rdf) => rdf -> Triples-expandTriples rdf = expandTriples' [] (baseUrl rdf) (prefixMappings rdf) (triplesOf rdf)+)+where -expandTriples' :: Triples -> Maybe BaseUrl -> PrefixMappings -> Triples -> Triples-expandTriples' acc _ _ [] = acc-expandTriples' acc baseUrl prefixMappings (t:rest) = expandTriples' (normalize baseUrl prefixMappings t : acc) baseUrl prefixMappings rest- where normalize baseUrl prefixMappings = expandPrefixes prefixMappings . expandBaseUrl baseUrl- expandBaseUrl (Just _) triple = triple- expandBaseUrl Nothing triple = triple- expandPrefixes _ triple = triple+import Data.RDF.Namespace+import Data.RDF.TriplesGraph+import Data.RDF.MGraph+import Text.RDF.RDF4H.NTriplesSerializer+import Text.RDF.RDF4H.TurtleSerializer+import Text.RDF.RDF4H.NTriplesParser+import Text.RDF.RDF4H.TurtleParser+import Data.RDF.Types+import Data.RDF.Query
src/Data/RDF/MGraph.hs view
@@ -4,7 +4,8 @@ where -import Data.RDF+import Data.RDF.Types+import Data.RDF.Query import Data.RDF.Namespace import Data.Map(Map) import qualified Data.Map as Map
src/Data/RDF/Namespace.hs view
@@ -15,11 +15,9 @@ ) where -import Text.Printf-import Data.Map(Map)-import qualified Data.Map as Map-import qualified Data.List as List import qualified Data.Text as T+import Data.RDF.Types+import qualified Data.Map as Map standard_namespaces :: [Namespace] standard_namespaces = [rdf, rdfs, dc, dct, owl, xsd, skos, foaf, ex, ex2]@@ -73,15 +71,6 @@ ex2 :: Namespace ex2 = mkPrefixedNS' "ex2" "http://www2.example.org/" --- |An alias for a map from prefix to namespace URI.-newtype PrefixMappings = PrefixMappings (Map T.Text T.Text)- deriving (Eq, Ord)-instance Show PrefixMappings where- -- This is really inefficient, but it's not used much so not what- -- worth optimizing yet.- show (PrefixMappings pmap) = printf "PrefixMappings [%s]" mappingsStr- where showPM = show . PrefixMapping- mappingsStr = List.intercalate ", " (map showPM (Map.toList pmap)) -- |Perform a left-biased merge of the two sets of prefix mappings. mergePrefixMappings :: PrefixMappings -> PrefixMappings -> PrefixMappings@@ -93,20 +82,10 @@ toPMList :: PrefixMappings -> [(T.Text, T.Text)] toPMList (PrefixMappings m) = Map.toList m --- |A mapping of a prefix to the URI for that prefix.-newtype PrefixMapping = PrefixMapping (T.Text, T.Text)- deriving (Eq, Ord)-instance Show PrefixMapping where- show (PrefixMapping (prefix, uri)) = printf "PrefixMapping (%s, %s)" (show prefix) (show uri)- -- |Make a URI consisting of the given namespace and the given localname. mkUri :: Namespace -> T.Text -> T.Text mkUri ns local = uriOf ns `T.append` local --- |Represents a namespace as either a prefix and uri, respectively,--- or just a uri.-data Namespace = PrefixedNS T.Text T.Text -- prefix and ns uri- | PlainNS T.Text -- ns uri alone -- |Make a namespace for the given URI reference. mkPlainNS :: T.Text -> Namespace@@ -122,16 +101,6 @@ -- automatically. mkPrefixedNS' :: String -> String -> Namespace mkPrefixedNS' s1 s2 = mkPrefixedNS (T.pack s1) (T.pack s2)--instance Eq Namespace where- (PrefixedNS _ u1) == (PrefixedNS _ u2) = u1 == u2- (PlainNS u1) == (PlainNS u2) = u1 == u2- (PrefixedNS _ u1) == (PlainNS u2) = u1 == u2- (PlainNS u1) == (PrefixedNS _ u2) = u1 == u2--instance Show Namespace where- show (PlainNS uri) = T.unpack uri- show (PrefixedNS prefix uri) = printf "(PrefixNS %s %s)" (T.unpack prefix) (T.unpack uri) -- |Determine the URI of the given namespace. uriOf :: Namespace -> T.Text
+ src/Data/RDF/Query.hs view
@@ -0,0 +1,118 @@++module Data.RDF.Query (++ -- * Query functions+ sortTriples, equalSubjects, equalPredicates, equalObjects,+ subjectOf, predicateOf, objectOf, isEmpty,+ rdfContainsNode, tripleContainsNode, removeDupes,+ listSubjectsWithPredicate, listObjectsOfPredicate,++ -- * RDF graph functions+ isIsomorphic, expandTriples, fromEither++) where++import Data.RDF.Types+import Data.List++-- |Answer the given list of triples in sorted order.+sortTriples :: Triples -> Triples+sortTriples = sort++-- |Answer the subject node of the triple.+{-# INLINE subjectOf #-}+subjectOf :: Triple -> Node+subjectOf (Triple s _ _) = s++-- |Answer the predicate node of the triple.+{-# INLINE predicateOf #-}+predicateOf :: Triple -> Node+predicateOf (Triple _ p _) = p++-- |Answer the object node of the triple.+{-# INLINE objectOf #-}+objectOf :: Triple -> Node+objectOf (Triple _ _ o) = o++-- |Answer if rdf contains node.+rdfContainsNode :: forall rdf. (RDF rdf) => rdf -> Node -> Bool+rdfContainsNode rdf node =+ let ts = triplesOf rdf+ xs = map (tripleContainsNode node) ts+ in elem True xs++-- |Answer if triple contains node.+tripleContainsNode :: Node -> Triple -> Bool+{-# INLINE tripleContainsNode #-}+tripleContainsNode node t = + subjectOf t == node || predicateOf t == node || objectOf t == node+++-- |Determine whether two triples have equal subjects.+equalSubjects :: Triple -> Triple -> Bool+equalSubjects (Triple s1 _ _) (Triple s2 _ _) = s1 == s2++-- |Determine whether two triples have equal predicates.+equalPredicates :: Triple -> Triple -> Bool+equalPredicates (Triple _ p1 _) (Triple _ p2 _) = p1 == p2++-- |Determine whether two triples have equal objects.+equalObjects :: Triple -> Triple -> Bool+equalObjects (Triple _ _ o1) (Triple _ _ o2) = o1 == o2++-- |Determines whether the 'RDF' contains zero triples.+isEmpty :: RDF rdf => rdf -> Bool+isEmpty rdf =+ let ts = triplesOf rdf+ in null ts++-- |Lists of all subjects of triples with the given predicate.+listSubjectsWithPredicate :: RDF rdf => rdf -> Predicate -> [Subject]+listSubjectsWithPredicate rdf pred =+ listNodesWithPredicate rdf pred subjectOf++-- |Lists of all objects of triples with the given predicate.+listObjectsOfPredicate :: RDF rdf => rdf -> Predicate -> [Object]+listObjectsOfPredicate rdf pred =+ listNodesWithPredicate rdf pred objectOf++listNodesWithPredicate :: RDF rdf => rdf -> Predicate -> (Triple -> Node) -> [Node]+listNodesWithPredicate rdf pred f =+ let ts = triplesOf rdf+ xs = filter (\t -> predicateOf t == pred) ts+ in map f xs++-- |Convert a parse result into an RDF if it was successful+-- and error and terminate if not.+fromEither :: RDF rdf => Either ParseFailure rdf -> rdf+fromEither res =+ case res of+ (Left err) -> error (show err)+ (Right rdf) -> rdf++-- |Remove duplicate triples, returning unique triples. This +-- function may return the triples in a different order than +-- given.+removeDupes :: Triples -> Triples+removeDupes = map head . group . sort++-- |This determines if two RDF representations are equal regardless of blank+-- node names, triple order and prefixes. In math terms, this is the \simeq+-- latex operator, or ~=+isIsomorphic :: forall rdf1 rdf2. (RDF rdf1, RDF rdf2) => rdf1 -> rdf2 -> Bool+isIsomorphic g1 g2 = normalize g1 == normalize g2+ where normalize :: forall rdf. (RDF rdf) => rdf -> Triples+ normalize = sort . nub . expandTriples++-- |Expand the triples in a graph with the prefix map and base URL for that+-- graph.+expandTriples :: (RDF rdf) => rdf -> Triples+expandTriples rdf = expandTriples' [] (baseUrl rdf) (prefixMappings rdf) (triplesOf rdf)++expandTriples' :: Triples -> Maybe BaseUrl -> PrefixMappings -> Triples -> Triples+expandTriples' acc _ _ [] = acc+expandTriples' acc baseUrl prefixMappings (t:rest) = expandTriples' (normalize baseUrl prefixMappings t : acc) baseUrl prefixMappings rest+ where normalize baseUrl prefixMappings = expandPrefixes prefixMappings . expandBaseUrl baseUrl+ expandBaseUrl (Just _) triple = triple+ expandBaseUrl Nothing triple = triple+ expandPrefixes _ triple = triple
src/Data/RDF/TriplesGraph.hs view
@@ -12,7 +12,8 @@ where -import Data.RDF+import Data.RDF.Types+import Data.RDF.Query import Data.RDF.Namespace import qualified Data.Map as Map
+ src/Data/RDF/Types.hs view
@@ -0,0 +1,511 @@++module Data.RDF.Types (++ -- * RDF triples, nodes and literals+ LValue(PlainL,PlainLL,TypedL),+ Node(UNode,BNode,BNodeGen,LNode), Subject, Predicate, Object,+ Triple(Triple), Triples, View(view),++ -- * Constructor functions+ plainL,plainLL,typedL,+ unode,bnode,lnode,triple,++ -- * Node query function+ isUNode,isLNode,isBNode,++ -- * RDF Type+ RDF(baseUrl,prefixMappings,addPrefixMappings,empty,mkRdf,triplesOf,select,query),++ -- * Parsing RDF+ RdfParser(parseString,parseFile,parseURL),++ -- * Serializing RDF+ RdfSerializer(hWriteRdf,writeRdf,hWriteH,writeH,hWriteTs,hWriteT,writeT, writeTs,hWriteN, writeN),++ -- * Namespaces and Prefixes+ Namespace(PrefixedNS,PlainNS),+ PrefixMappings(PrefixMappings),PrefixMapping(PrefixMapping),++ -- * Supporting types+ BaseUrl(BaseUrl), NodeSelector, ParseFailure(ParseFailure),++) where++import qualified Data.Text as T+import System.IO+import Text.Printf+import Data.Map(Map)+import qualified Data.List as List+import qualified Data.Map as Map++-------------------+-- LValue and constructor functions++-- |The actual value of an RDF literal, represented as the 'LValue'+-- parameter of an 'LNode'.+data LValue =+ -- Constructors are not exported, because we need to have more+ -- control over the format of the literal text that we store.++ -- |A plain (untyped) literal value in an unspecified language.+ PlainL !T.Text++ -- |A plain (untyped) literal value with a language specifier.+ | PlainLL !T.Text !T.Text++ -- |A typed literal value consisting of the literal value and+ -- the URI of the datatype of the value, respectively.+ | TypedL !T.Text !T.Text++-- |Return a PlainL LValue for the given string value.+{-# INLINE plainL #-}+plainL :: T.Text -> LValue+plainL = PlainL++-- |Return a PlainLL LValue for the given string value and language,+-- respectively.+{-# INLINE plainLL #-}+plainLL :: T.Text -> T.Text -> LValue+plainLL = PlainLL++-- |Return a TypedL LValue for the given string value and datatype URI,+-- respectively.+{-# INLINE typedL #-}+typedL :: T.Text -> T.Text -> LValue+typedL val dtype = TypedL (canonicalize dtype val) dtype++-------------------+-- Node and constructor functions++-- |An RDF node, which may be either a URIRef node ('UNode'), a blank+-- node ('BNode'), or a literal node ('LNode').+data Node =++ -- |An RDF URI reference. See+ -- <http://www.w3.org/TR/rdf-concepts/#section-Graph-URIref> for more+ -- information.+ UNode !T.Text++ -- |An RDF blank node. See+ -- <http://www.w3.org/TR/rdf-concepts/#section-blank-nodes> for more+ -- information.+ | BNode !T.Text++ -- |An RDF blank node with an auto-generated identifier, as used in+ -- Turtle.+ | BNodeGen !Int++ -- |An RDF literal. See+ -- <http://www.w3.org/TR/rdf-concepts/#section-Graph-Literal> for more+ -- information.+ | LNode !LValue++-- |An alias for 'Node', defined for convenience and readability purposes.+type Subject = Node++-- |An alias for 'Node', defined for convenience and readability purposes.+type Predicate = Node++-- |An alias for 'Node', defined for convenience and readability purposes.+type Object = Node++-- |Return a URIRef node for the given bytetring URI.+{-# INLINE unode #-}+unode :: T.Text -> Node+unode = UNode++-- |Return a blank node using the given string identifier.+{-# INLINE bnode #-}+bnode :: T.Text -> Node+bnode = BNode++-- |Return a literal node using the given LValue.+{-# INLINE lnode #-}+lnode :: LValue -> Node+lnode = LNode++-------------------+-- Triple and constructor functions++-- |An RDF triple is a statement consisting of a subject, predicate,+-- and object, respectively.+--+-- See <http://www.w3.org/TR/rdf-concepts/#section-triples> for+-- more information.+data Triple = Triple !Node !Node !Node++-- |A list of triples. This is defined for convenience and readability.+type Triples = [Triple]++-- |A smart constructor function for 'Triple' that verifies the node arguments+-- are of the correct type and creates the new 'Triple' if so or calls 'error'.+-- /subj/ must be a 'UNode' or 'BNode', and /pred/ must be a 'UNode'.+triple :: Subject -> Predicate -> Object -> Triple+triple subj pred obj+ | isLNode subj = error $ "subject must be UNode or BNode: " ++ show subj+ | isLNode pred = error $ "predicate must be UNode, not LNode: " ++ show pred+ | isBNode pred = error $ "predicate must be UNode, not BNode: " ++ show pred+ | otherwise = Triple subj pred obj++-- |Answer if given node is a URI Ref node.+{-# INLINE isUNode #-}+isUNode :: Node -> Bool+isUNode (UNode _) = True+isUNode _ = False++-- |Answer if given node is a blank node.+{-# INLINE isBNode #-}+isBNode :: Node -> Bool+isBNode (BNode _) = True+isBNode (BNodeGen _) = True+isBNode _ = False++-- |Answer if given node is a literal node.+{-# INLINE isLNode #-}+isLNode :: Node -> Bool+isLNode (LNode _) = True+isLNode _ = False++-- |A type class for ADTs that expose views to clients.+class View a b where+ view :: a -> b++-- |An RDF value is a set of (unique) RDF triples, together with the+-- operations defined upon them.+--+-- For information about the efficiency of the functions, see the+-- documentation for the particular RDF instance.+--+-- For more information about the concept of an RDF graph, see+-- the following: <http://www.w3.org/TR/rdf-concepts/#section-rdf-graph>.+class RDF rdf where++ -- |Return the base URL of this RDF, if any.+ baseUrl :: rdf -> Maybe BaseUrl++ -- |Return the prefix mappings defined for this RDF, if any.+ prefixMappings :: rdf -> PrefixMappings++ -- |Return an RDF with the specified prefix mappings merged with+ -- the existing mappings. If the Bool arg is True, then a new mapping+ -- for an existing prefix will replace the old mapping; otherwise,+ -- the new mapping is ignored.+ addPrefixMappings :: rdf -> PrefixMappings -> Bool -> rdf++ -- |Return an empty RDF.+ empty :: rdf++ -- |Return a RDF containing all the given triples. Handling of duplicates+ -- in the input depend on the particular RDF implementation.+ mkRdf :: Triples -> Maybe BaseUrl -> PrefixMappings -> rdf++ -- |Return all triples in the RDF, as a list.+ triplesOf :: rdf -> Triples++ -- |Select the triples in the RDF that match the given selectors.+ --+ -- The three NodeSelector parameters are optional functions that match+ -- the respective subject, predicate, and object of a triple. The triples+ -- returned are those in the given graph for which the first selector+ -- returns true when called on the subject, the second selector returns+ -- true when called on the predicate, and the third selector returns true+ -- when called on the ojbect. A 'Nothing' parameter is equivalent to a+ -- function that always returns true for the appropriate node; but+ -- implementations may be able to much more efficiently answer a select+ -- that involves a 'Nothing' parameter rather than an @(id True)@ parameter.+ --+ -- The following call illustrates the use of select, and would result in+ -- the selection of all and only the triples that have a blank node+ -- as subject and a literal node as object:+ --+ -- > select gr (Just isBNode) Nothing (Just isLNode)+ --+ -- Note: this function may be very slow; see the documentation for the+ -- particular RDF implementation for more information.+ select :: rdf -> NodeSelector -> NodeSelector -> NodeSelector -> Triples++ -- |Return the triples in the RDF that match the given pattern, where+ -- the pattern (3 Maybe Node parameters) is interpreted as a triple pattern.+ --+ -- The @Maybe Node@ params are interpreted as the subject, predicate, and+ -- object of a triple, respectively. @Just n@ is true iff the triple has+ -- a node equal to @n@ in the appropriate location; @Nothing@ is always+ -- true, regardless of the node in the appropriate location.+ --+ -- For example, @ query rdf (Just n1) Nothing (Just n2) @ would return all+ -- and only the triples that have @n1@ as subject and @n2@ as object,+ -- regardless of the predicate of the triple.+ query :: rdf -> Maybe Node -> Maybe Node -> Maybe Node -> Triples++-- |An RdfParser is a parser that knows how to parse 1 format of RDF and+-- can parse an RDF document of that type from a string, a file, or a URL.+-- Required configuration options will vary from instance to instance.+class RdfParser p where++ -- |Parse RDF from the given text, yielding a failure with error message or+ -- the resultant RDF.+ parseString :: forall rdf. (RDF rdf) => p -> T.Text -> Either ParseFailure rdf++ -- |Parse RDF from the local file with the given path, yielding a failure with error+ -- message or the resultant RDF in the IO monad.+ parseFile :: forall rdf. (RDF rdf) => p -> String -> IO (Either ParseFailure rdf)++ -- |Parse RDF from the remote file with the given HTTP URL (https is not supported),+ -- yielding a failure with error message or the resultant graph in the IO monad.+ parseURL :: forall rdf. (RDF rdf) => p -> String -> IO (Either ParseFailure rdf)+++-- |An RdfSerializer is a serializer of RDF to some particular output format, such as+-- NTriples or Turtle.+class RdfSerializer s where+ -- |Write the RDF to a file handle using whatever configuration is specified by+ -- the first argument.+ hWriteRdf :: forall rdf. (RDF rdf) => s -> Handle -> rdf -> IO ()++ -- |Write the RDF to stdout; equivalent to @'hWriteRdf' stdout@.+ writeRdf :: forall rdf. (RDF rdf) => s -> rdf -> IO ()++ -- |Write to the file handle whatever header information is required based on+ -- the output format. For example, if serializing to Turtle, this method would+ -- write the necessary \@prefix declarations and possibly a \@baseUrl declaration,+ -- whereas for NTriples, there is no header section at all, so this would be a no-op.+ hWriteH :: forall rdf. (RDF rdf) => s -> Handle -> rdf -> IO ()++ -- |Write header information to stdout; equivalent to @'hWriteRdf' stdout@.+ writeH :: forall rdf. (RDF rdf) => s -> rdf -> IO ()++ -- |Write some triples to a file handle using whatever configuration is specified+ -- by the first argument. + -- + -- WARNING: if the serialization format has header-level information + -- that should be output (e.g., \@prefix declarations for Turtle), then you should+ -- use 'hWriteG' instead of this method unless you're sure this is safe to use, since+ -- otherwise the resultant document will be missing the header information and + -- will not be valid.+ hWriteTs :: s -> Handle -> Triples -> IO ()++ -- |Write some triples to stdout; equivalent to @'hWriteTs' stdout@.+ writeTs :: s -> Triples -> IO ()++ -- |Write a single triple to the file handle using whatever configuration is + -- specified by the first argument. The same WARNING applies as to 'hWriteTs'.+ hWriteT :: s -> Handle -> Triple -> IO ()++ -- |Write a single triple to stdout; equivalent to @'hWriteT' stdout@.+ writeT :: s -> Triple -> IO ()++ -- |Write a single node to the file handle using whatever configuration is + -- specified by the first argument. The same WARNING applies as to 'hWriteTs'.+ hWriteN :: s -> Handle -> Node -> IO ()++ -- |Write a single node to sdout; equivalent to @'hWriteN' stdout@.+ writeN :: s -> Node -> IO ()+++-- |The base URL of an RDF.+newtype BaseUrl = BaseUrl T.Text+ deriving (Eq, Ord, Show)++-- |A 'NodeSelector' is either a function that returns 'True'+-- or 'False' for a node, or Nothing, which indicates that all+-- nodes would return 'True'.+--+-- The selector is said to select, or match, the nodes for+-- which it returns 'True'.+--+-- When used in conjunction with the 'select' method of 'Graph', three+-- node selectors are used to match a triple.+type NodeSelector = Maybe (Node -> Bool)++-- |Represents a failure in parsing an N-Triples document, including+-- an error message with information about the cause for the failure.+newtype ParseFailure = ParseFailure String+ deriving (Eq, Show)++-- |A node is equal to another node if they are both the same type+-- of node and if the field values are equal.+instance Eq Node where+ (UNode bs1) == (UNode bs2) = bs1 == bs2+ (BNode bs1) == (BNode bs2) = bs1 == bs2+ (BNodeGen i1) == (BNodeGen i2) = i1 == i2+ (LNode l1) == (LNode l2) = l1 == l2+ _ == _ = False++-- |Node ordering is defined first by type, with Unode < BNode < BNodeGen+-- < LNode PlainL < LNode PlainLL < LNode TypedL, and secondly by+-- the natural ordering of the node value.+--+-- E.g., a '(UNode _)' is LT any other type of node, and a+-- '(LNode (TypedL _ _))' is GT any other type of node, and the ordering+-- of '(BNodeGen 44)' and '(BNodeGen 3)' is that of the values, or+-- 'compare 44 3', GT.+instance Ord Node where+ compare = compareNode++compareNode :: Node -> Node -> Ordering+compareNode (UNode bs1) (UNode bs2) = compare bs1 bs2+compareNode (UNode _) _ = LT+compareNode (BNode bs1) (BNode bs2) = compare bs1 bs2+compareNode (BNode _) (UNode _) = GT+compareNode (BNode _) _ = LT+compareNode (BNodeGen i1) (BNodeGen i2) = compare i1 i2+compareNode (BNodeGen _) (LNode _) = LT+compareNode (BNodeGen _) _ = GT+compareNode (LNode (PlainL bs1)) (LNode (PlainL bs2)) = compare bs1 bs2+compareNode (LNode (PlainL _)) (LNode _) = LT+compareNode (LNode (PlainLL bs1 bs1')) (LNode (PlainLL bs2 bs2')) =+ case compare bs1' bs2' of+ EQ -> compare bs1 bs2+ LT -> LT+ GT -> GT+compareNode (LNode (PlainLL _ _)) (LNode (PlainL _)) = GT+compareNode (LNode (PlainLL _ _)) (LNode _) = LT+compareNode (LNode (TypedL bsType1 bs1)) (LNode (TypedL bsType2 bs2)) =+ case compare bs1 bs2 of+ EQ -> compare bsType1 bsType2+ LT -> LT+ GT -> GT+compareNode (LNode (TypedL _ _)) (LNode _) = GT+compareNode (LNode _) _ = GT++-- |Two triples are equal iff their respective subjects, predicates, and objects+-- are equal.+instance Eq Triple where+ (Triple s1 p1 o1) == (Triple s2 p2 o2) = s1 == s2 && p1 == p2 && o1 == o2++-- |The ordering of triples is based on that of the subject, predicate, and object+-- of the triple, in that order.+instance Ord Triple where+ (Triple s1 p1 o1) `compare` (Triple s2 p2 o2) =+ case compareNode s1 s2 of+ EQ -> case compareNode p1 p2 of+ EQ -> compareNode o1 o2+ LT -> LT+ GT -> GT+ GT -> GT+ LT -> LT++-- |Two 'LValue' values are equal iff they are of the same type and all fields are+-- equal.+instance Eq LValue where+ (PlainL bs1) == (PlainL bs2) = bs1 == bs2+ (PlainLL bs1 bs1') == (PlainLL bs2 bs2') = bs1' == bs2' && bs1 == bs2+ (TypedL bsType1 bs1) == (TypedL bsType2 bs2) = bsType1 == bsType2 && bs1 == bs2+ _ == _ = False++-- |Ordering of 'LValue' values is as follows: (PlainL _) < (PlainLL _ _)+-- < (TypedL _ _), and values of the same type are ordered by field values,+-- with '(PlainLL literalValue language)' being ordered by language first and+-- literal value second, and '(TypedL literalValue datatypeUri)' being ordered+-- by datatype first and literal value second.+instance Ord LValue where+ compare = compareLValue++{-# INLINE compareLValue #-}+compareLValue :: LValue -> LValue -> Ordering+compareLValue (PlainL bs1) (PlainL bs2) = compare bs1 bs2+compareLValue (PlainL _) _ = LT+compareLValue _ (PlainL _) = GT+compareLValue (PlainLL bs1 bs1') (PlainLL bs2 bs2') =+ case compare bs1' bs2' of+ EQ -> compare bs1 bs2+ GT -> GT+ LT -> LT+compareLValue (PlainLL _ _) _ = LT+compareLValue _ (PlainLL _ _) = GT+compareLValue (TypedL l1 t1) (TypedL l2 t2) =+ case compare t1 t2 of+ EQ -> compare l1 l2+ GT -> GT+ LT -> LT++-- String representations of the various data types; generally NTriples-like.++instance Show Triple where+ show (Triple s p o) =+ printf "Triple(%s,%s,%s)" (show s) (show p) (show o)++instance Show Node where+ show (UNode uri) = "UNode(" ++ show uri ++ ")"+ show (BNode i) = "BNode(" ++ show i ++ ")"+ show (BNodeGen genId) = "BNodeGen(" ++ show genId ++ ")"+ show (LNode lvalue) = "LNode(" ++ show lvalue ++ ")"++instance Show LValue where+ show (PlainL lit) = "PlainL(" ++ T.unpack lit ++ ")"+ show (PlainLL lit lang) = "PlainLL(" ++ T.unpack lit ++ ", " ++ T.unpack lang ++ ")"+ show (TypedL lit dtype) = "TypedL(" ++ T.unpack lit ++ "," ++ show dtype ++ ")"++------------------------+-- Prefix mappings++-- |Represents a namespace as either a prefix and uri, respectively,+-- or just a uri.+data Namespace = PrefixedNS T.Text T.Text -- prefix and ns uri+ | PlainNS T.Text -- ns uri alone++instance Eq Namespace where+ (PrefixedNS _ u1) == (PrefixedNS _ u2) = u1 == u2+ (PlainNS u1) == (PlainNS u2) = u1 == u2+ (PrefixedNS _ u1) == (PlainNS u2) = u1 == u2+ (PlainNS u1) == (PrefixedNS _ u2) = u1 == u2++instance Show Namespace where+ show (PlainNS uri) = T.unpack uri+ show (PrefixedNS prefix uri) = printf "(PrefixNS %s %s)" (T.unpack prefix) (T.unpack uri)++-- |An alias for a map from prefix to namespace URI.+newtype PrefixMappings = PrefixMappings (Map T.Text T.Text)+ deriving (Eq, Ord)+instance Show PrefixMappings where+ -- This is really inefficient, but it's not used much so not what+ -- worth optimizing yet.+ show (PrefixMappings pmap) = printf "PrefixMappings [%s]" mappingsStr+ where showPM = show . PrefixMapping+ mappingsStr = List.intercalate ", " (map showPM (Map.toList pmap))++-- |A mapping of a prefix to the URI for that prefix.+newtype PrefixMapping = PrefixMapping (T.Text, T.Text)+ deriving (Eq, Ord)+instance Show PrefixMapping where+ show (PrefixMapping (prefix, uri)) = printf "PrefixMapping (%s, %s)" (show prefix) (show uri)+++-----------------+-- Internal canonicalize functions, don't export++-- |Canonicalize the given 'T.Text' value using the 'T.Text'+-- as the datatype URI.+{-# NOINLINE canonicalize #-}+canonicalize :: T.Text -> T.Text -> T.Text+canonicalize typeTxt litValue =+ case Map.lookup typeTxt canonicalizerTable of+ Nothing -> litValue+ Just fn -> fn litValue++-- A table of mappings from a 'T.Text' URI (reversed as+-- they are) to a function that canonicalizes a T.Text+-- assumed to be of that type.+{-# NOINLINE canonicalizerTable #-}+canonicalizerTable :: Map T.Text (T.Text -> T.Text)+canonicalizerTable =+ Map.fromList [(integerUri, _integerStr), (doubleUri, _doubleStr),+ (decimalUri, _decimalStr)]+ where+ integerUri = "http://www.w3.org/2001/XMLSchema#integer"+ decimalUri = "http://www.w3.org/2001/XMLSchema#decimal"+ doubleUri = "http://www.w3.org/2001/XMLSchema#double"++_integerStr, _decimalStr, _doubleStr :: T.Text -> T.Text+_integerStr = T.dropWhile (== '0')++-- exponent: [eE] ('-' | '+')? [0-9]++-- ('-' | '+') ? ( [0-9]+ '.' [0-9]* exponent | '.' ([0-9])+ exponent | ([0-9])+ exponent )+_doubleStr s = T.pack $ show (read $ T.unpack s :: Double)++-- ('-' | '+')? ( [0-9]+ '.' [0-9]* | '.' ([0-9])+ | ([0-9])+ )+_decimalStr s = -- haskell double parser doesn't handle '1.'..,+ case T.last s of -- so we add a zero if that's the case and then parse+ '.' -> f (s `T.snoc` '0')+ _ -> f s+ where f s' = T.pack $ show (read $ T.unpack s' :: Double)
src/Data/RDF/Utils.hs view
@@ -1,13 +1,11 @@ module Data.RDF.Utils (- t2s, s2t, hPutStrRev, canonicalize+ t2s, s2t, hPutStrRev ) where import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) import qualified Data.ByteString as B-import Data.Map(Map)-import qualified Data.Map as Map import System.IO -- |A convenience function for converting from a bytestring to a string.@@ -25,40 +23,3 @@ hPutStrRev :: Handle -> T.Text -> IO () hPutStrRev h bs = B.hPutStr h ((encodeUtf8 . T.reverse) bs) --- |Canonicalize the given 'T.Text' value using the 'FastString'--- as the datatype URI.-{-# NOINLINE canonicalize #-}-canonicalize :: T.Text -> T.Text -> T.Text-canonicalize typeFs litValue =- case Map.lookup typeFs canonicalizerTable of- Nothing -> litValue- Just fn -> fn litValue---- A table of mappings from a FastString URI (reversed as--- they are) to a function that canonicalizes a T.Text--- assumed to be of that type.-{-# NOINLINE canonicalizerTable #-}-canonicalizerTable :: Map T.Text (T.Text -> T.Text)-canonicalizerTable =- Map.fromList [(integerUri, _integerStr), (doubleUri, _doubleStr),- (decimalUri, _decimalStr)]- where- integerUri = mkFsUri "http://www.w3.org/2001/XMLSchema#integer"- decimalUri = mkFsUri "http://www.w3.org/2001/XMLSchema#decimal"- doubleUri = mkFsUri "http://www.w3.org/2001/XMLSchema#double"- mkFsUri :: String -> T.Text- mkFsUri uri = s2t $! uri--_integerStr, _decimalStr, _doubleStr :: T.Text -> T.Text-_integerStr = T.dropWhile (== '0')---- exponent: [eE] ('-' | '+')? [0-9]+--- ('-' | '+') ? ( [0-9]+ '.' [0-9]* exponent | '.' ([0-9])+ exponent | ([0-9])+ exponent )-_doubleStr s = T.pack $ show (read $ T.unpack s :: Double)---- ('-' | '+')? ( [0-9]+ '.' [0-9]* | '.' ([0-9])+ | ([0-9])+ )-_decimalStr s = -- haskell double parser doesn't handle '1.'..,- case T.last s of -- so we add a zero if that's the case and then parse- '.' -> f (s `T.snoc` '0')- _ -> f s- where f s' = T.pack $ show (read $ T.unpack s' :: Double)
src/Rdf4hParseMain.hs view
@@ -1,8 +1,7 @@ module Main where -import Data.RDF+import Data.RDF.Types import Data.RDF.TriplesGraph- import Text.RDF.RDF4H.NTriplesParser import Text.RDF.RDF4H.NTriplesSerializer import Text.RDF.RDF4H.TurtleParser@@ -162,7 +161,7 @@ -- the version for the library as a whole, as given in rdf4h.cabal. -- TODO: should get this from cabal file rather than duplicating i here. version :: String-version = "0.9.1"+version = "1.0.2" options :: [OptDescr Flag] options =
src/Text/RDF/RDF4H/Interact.hs view
@@ -16,7 +16,7 @@ import qualified Data.Text as T -import Data.RDF+import Data.RDF.Types import Data.RDF.Utils() import Data.RDF.TriplesGraph() import Data.RDF.MGraph()
src/Text/RDF/RDF4H/NTriplesParser.hs view
@@ -3,11 +3,9 @@ module Text.RDF.RDF4H.NTriplesParser( NTriplesParser(NTriplesParser), ParseFailure-)--where+) where -import Data.RDF+import Data.RDF.Types import Text.RDF.RDF4H.ParserUtils import Data.Char(isLetter, isDigit, isLower) import qualified Data.Map as Map
src/Text/RDF/RDF4H/NTriplesSerializer.hs view
@@ -5,7 +5,7 @@ NTriplesSerializer(NTriplesSerializer) ) where -import Data.RDF+import Data.RDF.Types import Data.RDF.Utils import qualified Data.Text as T import Data.Text.Encoding
src/Text/RDF/RDF4H/ParserUtils.hs view
@@ -2,7 +2,7 @@ _parseURL, justTriples ) where -import Data.RDF+import Data.RDF.Types import Network.URI import Network.HTTP
src/Text/RDF/RDF4H/TurtleParser.hs view
@@ -7,7 +7,8 @@ where -import Data.RDF+import Data.RDF.Types+import Data.RDF.Utils import Data.RDF.Namespace import Text.RDF.RDF4H.ParserUtils import Text.Parsec
src/Text/RDF/RDF4H/TurtleSerializer.hs view
@@ -7,7 +7,8 @@ where -import Data.RDF+import Data.RDF.Types+import Data.RDF.Query import Data.RDF.Namespace import Data.RDF.Utils import qualified Data.Text as T
src/Text/RDF/RDF4H/XmlParser.hs view
@@ -5,7 +5,8 @@ parseXmlRDF, getRDF ) where -import Data.RDF+import Data.RDF.Types+import Data.RDF.Utils import qualified Data.Map as Map import Control.Arrow import Text.XML.HXT.Core