Skip to content

Instantly share code, notes, and snippets.

@peacememories
Last active August 4, 2018 03:13
Show Gist options
  • Save peacememories/c973b19fe7cc09686fc638c687cd77a7 to your computer and use it in GitHub Desktop.
Save peacememories/c973b19fe7cc09686fc638c687cd77a7 to your computer and use it in GitHub Desktop.
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecursiveDo #-}
module Main where
import Data.RDF
import RDFBuilder
import Data.Text as T
location lat lon name = blankNode
[ iri "a" "s:Place"
, child "won:hasBoundingBox" $ blankNode []
, string "s:geo" $ T.concat [lat, lon]
, string "s:name" $ name
]
rdfTest :: Rdf rdfImpl => RDFBuilder rdfImpl Node
rdfTest = do
rec b1 <- blankNode [child_ "ex:hasOtherNode" b2]
b2 <- blankNode [child_ "ex:hasOtherNode" b1]
namedNode
"ex:somenode"
[ child "won:hasLocation" $ location "28" "43" "A Place"
, child_ "ex:hasOtherNode" b1
]
main :: IO ()
main = do
let rdf = buildRDF rdfTest :: RDF AdjHashMap
writeRdf NTriplesSerializer rdf
module RDFBuilder
( RDFBuilder
, buildRDF
, blankNode
, namedNode
, literal
, string
, iri
, child
, child_
)
where
import Data.RDF as R
import Control.Monad.Trans.State.Lazy
import Data.Text as T
data RDFBuilderState rdfImpl =
RDFBuilderState
{ rdfStore :: RDF rdfImpl
, blankNodeIndex :: Int
}
type RDFBuilder rdfImpl = State (RDFBuilderState rdfImpl)
data NodeEntry rdfImpl =
NodeEntry Node (RDFBuilder rdfImpl Node)
literal :: Text -> LValue -> NodeEntry rdfImpl
literal predicate object = NodeEntry (UNode predicate) (return $ LNode object)
string :: Text -> Text -> NodeEntry rdfImpl
string predicate str = literal predicate $ PlainL str
iri :: Text -> Text -> NodeEntry rdfImpl
iri predicate object = NodeEntry (UNode predicate) (pure $ UNode object)
child :: Text -> RDFBuilder rdfImpl Node -> NodeEntry rdfImpl
child predicate = NodeEntry (UNode predicate)
child_ :: Text -> Node -> NodeEntry rdfImpl
child_ predicate object = NodeEntry (UNode predicate) (pure object)
buildRDF :: Rdf rdfImpl => RDFBuilder rdfImpl a -> RDF rdfImpl
buildRDF builder =
let (_, resultState) = runState builder
$ RDFBuilderState {rdfStore = R.empty, blankNodeIndex = 0}
in rdfStore resultState
createBlankNodeIri :: RDFBuilder rdfImpl Node
createBlankNodeIri = do
bni <- gets blankNodeIndex
modify $ \state -> state { blankNodeIndex = bni + 1 }
return $ BNodeGen bni
insertTriple :: Rdf rdfImpl => Triple -> RDFBuilder rdfImpl ()
insertTriple triple =
modify $ \state -> state { rdfStore = addTriple (rdfStore state) triple }
blankNode :: Rdf rdfImpl => [NodeEntry rdfImpl] -> RDFBuilder rdfImpl Node
blankNode predicateList = do
blankNodeName <- createBlankNodeIri
node blankNodeName predicateList
namedNode
:: Rdf rdfImpl => Text -> [NodeEntry rdfImpl] -> RDFBuilder rdfImpl Node
namedNode subject_ = node $ UNode subject_
node :: Rdf rdfImpl => Node -> [NodeEntry rdfImpl] -> RDFBuilder rdfImpl Node
node subject predicateList = do
mapM_
(\(NodeEntry predicate object_) -> do
object <- object_
let triple = Triple subject predicate object
insertTriple triple
)
predicateList
return subject
<ex:somenode> <ex:hasOtherNode> _:genid0 .
<ex:somenode> <won:hasLocation> _:genid2 .
_:genid2 <s:geo> "2843" .
_:genid2 <s:name> "A Place" .
_:genid2 <won:hasBoundingBox> _:genid3 .
_:genid2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <s:Place> .
_:genid0 <ex:hasOtherNode> _:genid1 .
_:genid1 <ex:hasOtherNode> _:genid0 .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment