Commits

Doug Burke committed bf4dbed

Namespace: use Text for Namespace prefix and ScopedName local part rather than String

  • Participants
  • Parent commits e0c3083
  • Branches parser-rewrite-polyparse

Comments (0)

Files changed (28)

 0.4.0.0:
 
   - Use polyparse rather than parsec-2 for parsing. As part of this, the
-    parsing is done using Text rather than String values. At present the
-    RDFLabel and RDFGraph classes have not been updated to use Text (so
-    some conversion between the two types is introduced). The eventual
-    plan is to use Text as much as sensible.
+    parsing is done using Text rather than String values, where sensible.
 
   - removed Swish.Utils.DateTime and Swish.Utils.TraceHelpers
 
   - removed _ from exported symbols; the conversion is mainly to camel case
     but some may retain lower case parts (e.g. xxx_1_1_inv to xxx11inv).
 
-  - Namespace now uses Maybe String to store the optional prefix rather than
-    an ad-hoc ""/"?" solution and URI rather than String for the URI.
-    QName also uses URIs and no longer exports the constructor so newQName
-    or related should be used to create QNames.
+  - Namespace now uses Maybe Text to store the optional prefix rather
+    than an ad-hoc ""/"?" solution and URI rather than String for the
+    URI.  The local part of ScopedName is now Text.  QName also uses
+    URIs and no longer exports the constructor so newQName or related
+    should be used to create QNames.
 
     We have currently lost N3 formatting of the default prefix (any default
     prefix elements end up getting written out fully qualified). The output

File Swish/RDF/Datatype.hs

-{-# LANGUAGE ExistentialQuantification, MultiParamTypeClasses #-}
+{-# LANGUAGE ExistentialQuantification, MultiParamTypeClasses, OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  ExistentialQuantification, MultiParamTypeClasses
+--  Portability :  ExistentialQuantification, MultiParamTypeClasses, OverloadedStrings
 --
 --  This module defines the structures used by Swish to represent and
 --  manipulate datatypes.  It is designed as a basis for handling datatyped

File Swish/RDF/N3Formatter.hs

   getFormulae,
   emptyRDFGraph
   , quote
+  , quoteT
   , resRdfFirst, resRdfRest, resRdfNil
   )
 
   ls <- sequence mls
   return $ mconcat ls
     where
-      pref (Just p,u) = nextLine $ mconcat ["@prefix ", B.fromString p, ": <", quoteB True (show u), "> ."]
+      pref (Just p,u) = nextLine $ mconcat ["@prefix ", B.fromText p, ": <", quoteB True (show u), "> ."]
       pref (_,u)      = nextLine $ mconcat ["@prefix : <", quoteB True (show u), "> ."]
 
 {-
           prefix = mapFindMaybe nsuri premap
           
           name   = case prefix of
-                     Just (Just p) -> quoteB True (p ++ ":" ++ local) -- TODO: what are quoting rules for QNames
-                     _ -> mconcat ["<", quoteB True (show nsuri ++ local), ">"]
+                     Just (Just p) -> B.fromText $ quoteT True $ mconcat [p, ":", local] -- TODO: what are quoting rules for QNames
+                     _ -> mconcat ["<", quoteB True (show nsuri ++ T.unpack local), ">"]
       
       {-
           name   = case prefix of
 
 -- the annotation for a literal (ie type or language)
 formatAnnotation :: ScopedName -> B.Builder
-formatAnnotation a  | isLang a  = "@" `mappend` B.fromString (langTag a)
+formatAnnotation a  | isLang a  = "@" `mappend` B.fromText (langTag a)
                     | otherwise = "^^" `mappend` showScopedName a
 
 {-

File Swish/RDF/N3Parser.hs

     , char
     , ichar
     , string
+    , stringT
     , symbol
     , lexeme
     , whiteSpace
         , prefixUris :: NamespaceMap        -- namespace prefix mapping table
         , syntaxUris :: SpecialMap          -- special name mapping table
         , nodeGen    :: Int                 -- blank node id generator
-        , keywordsList :: [String]          -- contents of the @keywords statement
+        , keywordsList :: [T.Text]          -- contents of the @keywords statement
         , allowLocalNames :: Bool           -- True if @keywords used so that bare names are QNames in default namespace
         }
 
 -- | Functions to update N3State vector (use with stUpdate)
 
-setPrefix :: Maybe String -> URI -> N3State -> N3State
+setPrefix :: Maybe T.Text -> URI -> N3State -> N3State
 setPrefix pre uri st =  st { prefixUris=p' }
     where
         p' = mapReplaceOrAdd (Namespace pre uri) (prefixUris st)
 
 -- | Set the list of tokens that can be used without needing the leading 
 -- \@ symbol.
-setKeywordsList :: [String] -> N3State -> N3State
+setKeywordsList :: [T.Text] -> N3State -> N3State
 setKeywordsList ks st = st { keywordsList = ks, allowLocalNames = True }
 
 --  Functions to access state:
 getSUri st nam = getScopedNameURI $ getSName st nam
 
 --  Map prefix to URI
-getPrefixURI :: N3State -> Maybe String -> Maybe URI
+getPrefixURI :: N3State -> Maybe T.Text -> Maybe URI
 getPrefixURI st pre = mapFindMaybe pre (prefixUris st)
 
-getKeywordsList :: N3State -> [String]
+getKeywordsList :: N3State -> [T.Text]
 getKeywordsList = keywordsList
 
 getAllowLocalNames :: N3State -> Bool
 
 parseNameFromText :: L.Text -> Either String String
 parseNameFromText =
-    parseAnyfromText n3Name Nothing
+    parseAnyfromText n3NameStr Nothing
 
 {-
 This has been made tricky by the attempt to remove the default list
 -- The @ character is optional if the keyword is in the
 -- keyword list
 --
-atSign :: String -> N3Parser ()
+atSign :: T.Text -> N3Parser ()
 atSign s = do
   st <- stGet
   
     then ignore $ optional p
     else p
          
-atWord :: String -> N3Parser String
+atWord :: T.Text -> N3Parser T.Text
 atWord s = do
   atSign s
   
   -- apply to both cases even though should only really be necessary
   -- when the at sign is not given
   --
-  lexeme $ string s *> notFollowedBy (== ':')
+  lexeme $ stringT s *> notFollowedBy (== ':')
   return s
 
 {-
   map chr
   (0x00b7 : [0x00c0..0x00d6] ++ [0x00d8..0x00f6] ++ [0x00f8..0x037d] ++ [0x037f..0x1fff] ++ [0x200c..0x200d] ++ [0x203f..0x2040] ++ [0x2070..0x218f] ++ [0x2c00..0x2fef] ++ [0x3001..0xd7ff] ++ [0xf900..0xfdcf] ++ [0xfdf0..0xfffd] ++ [0x00010000..0x000effff])
 
-n3Name :: N3Parser String
-n3Name = (:) <$> n3Init <*> n3Body
+n3Name :: N3Parser T.Text
+n3Name = T.cons <$> n3Init <*> n3Body
   where
     n3Init = satisfy (`elem` initChar)
-    n3Body = L.unpack <$> manySatisfy (`elem` bodyChar)
+    n3Body = L.toStrict <$> manySatisfy (`elem` bodyChar)
+
+n3NameStr :: N3Parser String
+n3NameStr = T.unpack <$> n3Name
 
 {-
 quickvariable ::=	\?[A-Z_a-z#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x02ff#x0370-#x037d#x037f-#x1fff#x200c-#x200d#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff][\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*
 
 -- TODO: is mapping to Var correct?
 quickVariable :: N3Parser RDFLabel
-quickVariable = char '?' *> (Var <$> n3Name) 
+quickVariable = char '?' *> (Var <$> n3NameStr) 
 
 {-
 string ::=	("""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*""")|("[^"\\]*(?:\\.[^"\\]*)*")
 addBase :: URI -> N3Parser ()
 addBase = stUpdate . setSUri "base" 
 
-addPrefix :: Maybe String -> URI -> N3Parser ()
+addPrefix :: Maybe T.Text -> URI -> N3Parser ()
 addPrefix p = stUpdate . setPrefix p 
 
 {-|
 Update the set of keywords that can be given without
 an \@ sign.
 -}
-updateKeywordsList :: [String] -> N3Parser ()
+updateKeywordsList :: [T.Text] -> N3Parser ()
 updateKeywordsList = stUpdate . setKeywordsList
 
 {-
 		|	void
 -}
 
-bareNameCsl :: N3Parser [String]
+bareNameCsl :: N3Parser [T.Text]
 bareNameCsl = sepBy (lexeme bareName) comma
 
-bareName :: N3Parser String
+bareName :: N3Parser T.Text
 bareName = n3Name 
 
 {-
 prefix ::=	([A-Z_a-z#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x02ff#x0370-#x037d#x037f-#x1fff#x200c-#x200d#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff][\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*)?:
 -}
 
-prefix :: N3Parser (Maybe String)
+prefix :: N3Parser (Maybe T.Text)
 prefix = optional (lexeme n3Name) <* char ':'
          
 
     where
       toSN p = ScopedName <$> p <*> (n3Name <|> return "")
           
-fullOrLocalQName :: String -> N3Parser ScopedName
+fullOrLocalQName :: T.Text -> N3Parser ScopedName
 fullOrLocalQName name = 
   (char ':' *> fullQName name)
   <|> localQName name
   
-fullQName :: String -> N3Parser ScopedName
+fullQName :: T.Text -> N3Parser ScopedName
 fullQName name = do
   pre <- findPrefix name
   lname <- n3Name <|> return ""
   return $ ScopedName pre lname
   
-findPrefix :: String -> N3Parser Namespace
+findPrefix :: T.Text -> N3Parser Namespace
 findPrefix pre = do
   st <- stGet
   case mapFindMaybe (Just pre) (prefixUris st) of
     Just uri -> return $ Namespace (Just pre) uri
-    Nothing  -> failBad $ "Prefix '" ++ pre ++ ":' not bound."
+    Nothing  -> failBad $ "Prefix '" ++ T.unpack pre ++ ":' not bound."
   
-localQName :: String -> N3Parser ScopedName
+localQName :: T.Text -> N3Parser ScopedName
 localQName name = do
   st <- stGet
   if getAllowLocalNames st
     then ScopedName <$> getDefaultPrefix <*> pure name
-    else fail ("Invalid 'bare' word: " ++ name)-- TODO: not ideal error message; can we handle this case differently?
+    else fail ("Invalid 'bare' word: " ++ T.unpack name)-- TODO: not ideal error message; can we handle this case differently?
 
 {-
 existential ::=		|	 "@forSome"  symbol_csl
   <|> literal
   <|> numericLiteral
   <|> quickVariable
-  <|> Blank <$> (string "_:" *> n3Name) -- TODO a hack that needs fixing
+  <|> Blank <$> (string "_:" *> n3NameStr) -- TODO a hack that needs fixing
   <|> Res <$> n3symbol
   
 {-  
 langcode = do
   h <- many1Satisfy (`elem` ['a'..'z'])
   mt <- optional ( L.append <$> (char '-' *> pure (L.singleton '-')) <*> many1Satisfy (`elem` ['a'..'z'] ++ ['0'..'9']))
-  return $ langName $ L.unpack $ L.append h (fromMaybe L.empty mt)
+  return $ langName $ L.toStrict $ L.append h (fromMaybe L.empty mt)
     
 {-
 decimal ::=	[-+]?[0-9]+(\.[0-9]+)?
   -- try (d2s <$> n3double)
   -- <|> try (mkTypedLit xsdDecimal <$> n3decimal)
   d2s <$> n3double
-  <|> mkTypedLit xsdDecimal <$> n3decimal
-  <|> mkTypedLit xsdInteger <$> n3integer
+  <|> mkTypedLit xsdDecimal . T.pack <$> n3decimal
+  <|> mkTypedLit xsdInteger . T.pack <$> n3integer
 
 n3sign :: N3Parser Char
 n3sign = char '+' <|> char '-'
 n3decimal :: N3Parser String
 n3decimal = (++) <$> n3integer <*> ( (:) <$> char '.' <*> many1 digit )
            
-n3double :: N3Parser String  
+n3double :: N3Parser String
 n3double = (++) <$> n3decimal <*> ( (:) <$> satisfy (`elem` "eE") <*> n3integer )
 
 -- Convert a double, as returned by n3double, into it's

File Swish/RDF/NTFormatter.hs

 formatLabel lab@(Blank _) = mapBlankNode lab
 formatLabel (Res sn) = return $ showScopedName sn
 formatLabel (Lit lit Nothing) = return $ quoteText lit
-formatLabel (Lit lit (Just nam)) | isLang nam = return $ mconcat [quoteText lit, at, B.fromString (langTag nam)]
+formatLabel (Lit lit (Just nam)) | isLang nam = return $ mconcat [quoteText lit, at, B.fromText (langTag nam)]
                                  | otherwise  = return $ mconcat [quoteText lit, carets, showScopedName nam]
 
 -- do not expect to get the following, but include
 -- TODO: can we use Network.URI to protect the URI?
 showScopedName :: ScopedName -> B.Builder
 showScopedName (ScopedName n l) = 
-  let uri = T.pack $ show (nsURI n) ++ l
+  let uri = T.pack (show (nsURI n)) `mappend` l
   in mconcat ["<", B.fromText (quote uri), ">"]
 
 {-

File Swish/RDF/NTParser.hs

 language = do
   h <- many1Satisfy (`elem` ['a'..'z'])
   mt <- optional ( L.cons <$> char '-' <*> many1Satisfy (`elem` (['a'..'z'] ++ ['0'..'9'])) )
-  return $ langName $ L.unpack $ L.append h $ fromMaybe L.empty mt
+  return $ langName $ L.toStrict $ L.append h $ fromMaybe L.empty mt
 
 {-
 String handling: 

File Swish/RDF/RDFDatatypeXsdInteger.hs

 import Control.Monad (liftM)
 import Data.Maybe (maybeToList)
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as B
 
 ------------------------------------------------------------
 ------------------------------------------------------------
 
 --  Local name for Integer datatype
-nameXsdInteger :: String
+nameXsdInteger :: T.Text
 nameXsdInteger      = "integer"
 
 -- |Type name for xsd:integer datatype
     ]
 
 mkIntRel2 ::
-    String -> DatatypeRelPr Integer -> UnaryFnTable Integer
+    T.Text -> DatatypeRelPr Integer -> UnaryFnTable Integer
     -> DatatypeRel Integer
 mkIntRel2 nam pr fns = DatatypeRel
     { dtRelName = ScopedName namespaceXsdInteger nam
     }
 
 mkIntRel3 ::
-    String -> DatatypeRelPr Integer -> BinaryFnTable Integer
+    T.Text -> DatatypeRelPr Integer -> BinaryFnTable Integer
     -> DatatypeRel Integer
 mkIntRel3 nam pr fns = DatatypeRel
     { dtRelName = ScopedName namespaceXsdInteger nam
     }
 
 mkIntRel3maybe ::
-    String -> DatatypeRelPr Integer -> BinMaybeFnTable Integer
+    T.Text -> DatatypeRelPr Integer -> BinMaybeFnTable Integer
     -> DatatypeRel Integer
 mkIntRel3maybe nam pr fns = DatatypeRel
     { dtRelName = ScopedName namespaceXsdInteger nam
 modXsdIntegerGe = modXsdIntegerCompare "ge" (>=)
 
 modXsdIntegerCompare ::
-    String -> (Integer->Integer->Bool) -> RDFDatatypeMod Integer
+    T.Text -> (Integer->Integer->Bool) -> RDFDatatypeMod Integer
 modXsdIntegerCompare nam rel = DatatypeMod
     { dmName = ScopedName namespaceXsdInteger nam
     , dmModf = [ f0 ]
   , mkPrefix namespaceXsdInteger
   ]
 
-mkAxiom :: String -> B.Builder -> RDFFormula
+mkAxiom :: T.Text -> B.Builder -> RDFFormula
 mkAxiom local gr =
     makeRDFFormula namespaceXsdInteger local (prefixXsdInteger `mappend` gr)
 

File Swish/RDF/RDFDatatypeXsdString.hs

 ------------------------------------------------------------
 
 --  Local name for Integer datatype
-nameXsdString :: String
+nameXsdString :: T.Text
 nameXsdString = "string"
 
 -- |Type name for @xsd:string@ datatype
     ]
 
 mkStrRel2 ::
-    String -> DatatypeRelPr T.Text -> UnaryFnTable T.Text
+    T.Text -> DatatypeRelPr T.Text -> UnaryFnTable T.Text
     -> DatatypeRel T.Text
 mkStrRel2 nam pr fns = DatatypeRel
     { dtRelName = ScopedName namespaceXsdString nam
 modXsdStringNe = modXsdStringCompare "ne" (/=)
 
 modXsdStringCompare ::
-    String -> (T.Text->T.Text->Bool) -> RDFDatatypeMod T.Text
+    T.Text -> (T.Text->T.Text->Bool) -> RDFDatatypeMod T.Text
 modXsdStringCompare nam rel = DatatypeMod
     { dmName = ScopedName namespaceXsdString nam
     , dmModf = [ f0 ]
   , mkPrefix namespaceXsdString
   ]
   
-mkAxiom :: String -> B.Builder -> RDFFormula
+mkAxiom :: T.Text -> B.Builder -> RDFFormula
 mkAxiom local gr =
     makeRDFFormula namespaceXsdString local (prefixXsdString `mappend` gr)
 

File Swish/RDF/RDFGraph.hs

     , isDatatyped, isMemberProp, isUri, isBlank, isQueryVar
     , getLiteralText, getScopedName, makeBlank
     , quote
+    , quoteT
       
       -- * RDF Graphs
     , RDFTriple
 import Network.URI (URI)
 
 import Data.Monoid (Monoid(..))
-import Data.Char (ord, isDigit, toLower)
+import Data.Char (ord, isDigit)
 import Data.List (intersect, union, findIndices, foldl')
 import Data.Ord (comparing)
 import Data.String (IsString(..))
     Lit s1 Nothing   == Lit s2 Nothing   = s1 == s2
     Lit s1 (Just t1) == Lit s2 (Just t2) = s1 == s2 && (t1 == t2 ||
                                                         (isLang t1 && isLang t2 &&
-                                                         (map toLower . langTag) t1 == (map toLower . langTag) t2))
+                                                         (T.toLower . langTag) t1 == (T.toLower . langTag) t2))
     
     _  == _ = False
 
     show (Res sn)           = show sn
     show (Lit st Nothing)   = quote1Str st
     show (Lit st (Just nam))
-        | isLang nam = quote1Str st ++ "@"  ++ langTag nam
+        | isLang nam = quote1Str st ++ "@"  ++ T.unpack (langTag nam)
         | nam `elem` [xsdBoolean, xsdDouble, xsdDecimal, xsdInteger] = T.unpack st
         | otherwise  = quote1Str st ++ "^^" ++ show nam
     show (Blank ln)         = "_:"++ln
     labelIsVar _            = False
     getLocal   (Blank loc)  = loc
     getLocal   (Var   loc)  = '?':loc
-    getLocal   (Res   sn)   = "Res_"++snLocal sn
+    getLocal   (Res   sn)   = "Res_" ++ T.unpack (snLocal sn)
     getLocal   (NoNode)     = "None"
     getLocal   _            = "Lit_"
     makeLabel  ('?':loc)    = Var loc
 showCanon :: RDFLabel -> String
 showCanon (Res sn)           = "<"++show (getScopedNameURI sn)++">"
 showCanon (Lit st (Just nam))
-        | isLang nam = quote1Str st ++ "@"  ++ langTag nam
+        | isLang nam = quote1Str st ++ "@"  ++ T.unpack (langTag nam)
         | otherwise  = quote1Str st ++ "^^" ++ show (getScopedNameURI nam)
 showCanon s                  = show s
 
 in a row.
 -}
 
+-- temporary conversion
+quoteT :: Bool -> T.Text -> T.Text
+quoteT f = T.pack . quote f . T.unpack 
+
 quote :: Bool -> String -> String
 quote _     []           = ""
 quote False s@(c:'"':[]) | c == '\\'  = s -- handle triple-quoted strings ending in "
 --  remaining characters of local name are all digits
 isMemberProp :: RDFLabel -> Bool
 isMemberProp (Res sn) = snScope sn == namespaceRDF &&
-                        head loc   == '_' &&
-                        all isDigit (tail loc)
+                        T.head loc   == '_' &&
+                        T.all isDigit (T.tail loc)
                         where
                             loc = snLocal sn
 isMemberProp _        = False
 
 data RevNamespace = RevNamespace Namespace
 
-instance LookupEntryClass RevNamespace URI (Maybe String) where
+instance LookupEntryClass RevNamespace URI (Maybe T.Text) where
     keyVal   (RevNamespace (Namespace pre uri)) = (uri,pre)
     newEntry (uri,pre) = RevNamespace (Namespace pre uri)
 

File Swish/RDF/RDFParser.hs

     , char
     , ichar
     , string
+    , stringT
     , symbol
     , lexeme
     , notFollowedBy
 string :: String -> Parser s String
 string = mapM char
   
+stringT :: T.Text -> Parser s T.Text
+stringT s = string (T.unpack s) >> return s
+
 skipMany :: Parser s a -> Parser s ()
 skipMany = ignore . many
   
 -- | Create a typed literal.
 mkTypedLit ::
   ScopedName -- ^ the type
-  -> String -- ^ the value
+  -> T.Text  -- ^ the value
   -> RDFLabel
-mkTypedLit u v = Lit (T.pack v) (Just u)
+mkTypedLit u v = Lit v (Just u)
 
 {-
 Handle hex encoding; the spec for N3 and NTriples suggest that

File Swish/RDF/RDFProofContext.hs

 import Data.Monoid (Monoid(..))
 import Data.Maybe (isJust, fromJust)
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as B
 
 ------------------------------------------------------------
 --  Define query binding filter auxiliaries
 ------------------------------------------------------------
 
-makeFormula :: Namespace -> String -> B.Builder -> RDFFormula
+makeFormula :: Namespace -> T.Text -> B.Builder -> RDFFormula
 makeFormula = makeRDFFormula
 
 requireAny :: [RDFVarBindingFilter] -> RDFVarBindingFilter

File Swish/RDF/RDFRuleset.hs

 import Data.Maybe (fromMaybe)
 import Data.Monoid (Monoid(..))
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as B
 
 ------------------------------------------------------------
 -- |Create an RDF formula.
 makeRDFFormula ::
     Namespace     -- ^ namespace to which the formula is allocated
-    -> String     -- ^ local name for the formula in the namespace
+    -> T.Text     -- ^ local name for the formula in the namespace
     -> B.Builder  -- ^ graph in Notation 3 format
     -> RDFFormula
 makeRDFFormula scope local gr = Formula
 --
 makeN3ClosureRule ::
     Namespace -- ^ namespace to which the rule is allocated
-    -> String -- ^ local name for the rule in the namespace
+    -> T.Text -- ^ local name for the rule in the namespace
     -> B.Builder 
     -- ^ the Notation3 representation
     --   of the antecedent graph.  (Note: multiple antecedents
 --
 makeN3ClosureSimpleRule ::
     Namespace -- ^ namespace to which the rule is allocated
-    -> String -- ^ local name for the rule in the namepace
+    -> T.Text -- ^ local name for the rule in the namepace
     -> B.Builder
     -- ^ the Notation3 representation
     --   of the antecedent graph.  (Note: multiple antecedents
 --
 makeN3ClosureModifyRule ::
     Namespace -- ^ namespace to which the rule is allocated
-    -> String -- ^ local name for the rule in the given namespace
+    -> T.Text -- ^ local name for the rule in the given namespace
     -> B.Builder -- ^ the Notation3 representation
     --                of the antecedent graph.  (Note: multiple antecedents
     --                can be handled by combining multiple graphs.)
 --
 makeN3ClosureAllocatorRule ::
     Namespace -- ^ namespace to which the rule is allocated
-    -> String -- ^ local name for the rule in the given namespace
+    -> T.Text -- ^ local name for the rule in the given namespace
     -> B.Builder -- ^ the Notation3 representation
     --                of the antecedent graph.  (Note: multiple antecedents
     --                can be handled by combining multiple graphs.)

File Swish/RDF/RDFVarBinding.hs

+{-# LANGUAGE OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  H98
+--  Portability :  OverloadedStrings
 --
 --  This module instantiates the `VarBinding` types and methods for use
 --  with RDF graph labels.

File Swish/RDF/Rule.hs

-{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE MultiParamTypeClasses, OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  MultiParamTypeClasses
+--  Portability :  MultiParamTypeClasses, OverloadedStrings
 --
 --  This module defines a framework for defining inference rules
 --  over some expression form.  It is intended to be used with

File Swish/RDF/VarBinding.hs

-{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
+{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  MultiParamTypeClasses, TypeSynonymInstances
+--  Portability :  MultiParamTypeClasses, TypeSynonymInstances, OverloadedStrings
 --
 --  This module defines functions for representing and manipulating query
 --  binding variable sets.  This is the key data that mediates between
 
 import Data.List (find, intersect, union, (\\), foldl')
 
+import Data.Monoid (mconcat)
+
+-- import qualified Data.Text as T
 
 ------------------------------------------------------------
 --  Query variable bindings
     (VarBindingModify nam1 app1 voc1 use1)
     (VarBindingModify nam2 app2 voc2 use2)
     | not (null use12) = Just VarBindingModify
-        { vbmName  = swishName ("_"++ snLocal nam1 ++"_"++ snLocal nam2 ++"_")
+        { vbmName  = swishName $ mconcat ["_", snLocal nam1, "_", snLocal nam2, "_"]
         , vbmApply = app2 . app1
         , vbmVocab = voc1 `union` voc2
         , vbmUsage = use12

File Swish/RDF/Vocabulary.hs

+{-# LANGUAGE OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  H98
+--  Portability :  OverloadedStrings
 --
 --  This module defines some commonly used vocabulary terms,
 --  using the 'Namespace' and 'ScopedName' data types.
 
 import Swish.Utils.Namespace (Namespace(..), ScopedName(..))
 
-import Data.Char (toLower)
+import Data.Monoid (mappend, mconcat)
 import Data.Maybe (fromMaybe)
 import Network.URI (parseURI)
 
+import qualified Data.Text as T
+
 ------------------------------------------------------------
 --  Define some common namespace values
 ------------------------------------------------------------
 
-toNS :: String -> String -> Namespace
-toNS p ustr = 
-  let uri = fromMaybe (error ("Unable to convert " ++ ustr ++ " to a URI")) $
+toNS :: T.Text -> T.Text -> Namespace
+toNS p utxt = 
+  let ustr = T.unpack utxt
+      uri = fromMaybe (error ("Unable to convert " ++ ustr ++ " to a URI")) $
             parseURI ustr
   in Namespace (Just p) uri
 
-namespaceXsdType :: String -> Namespace
-namespaceXsdType dtname = toNS ("xsd_"++dtname)
-                          ("http://id.ninebynine.org/2003/XMLSchema/"++dtname++"#")
+namespaceXsdType :: T.Text -> Namespace
+namespaceXsdType dtn = toNS ("xsd_" `mappend` dtn)
+                       (mconcat ["http://id.ninebynine.org/2003/XMLSchema/", dtn, "#"])
 
 namespaceRDF :: Namespace
 namespaceRDFS :: Namespace
 namespaceLang    = toNS "lang"    "http://id.ninebynine.org/2003/Swish/Lang/" -- To be replaced by urn:ietf:params:lang?
 namespaceDefault = toNS "default" "http://id.ninebynine.org/default/"
 
-swishName :: String -> ScopedName
+swishName :: T.Text -> ScopedName
 swishName = ScopedName namespaceSwish
 
 -----------------------------------------------------------
 --  Fortunately, they do not currently need to appear in Notation3 as
 --  distinct labels (but future developments may change that).
 
-langName :: String -> ScopedName
-langName = ScopedName namespaceLang . map toLower
+langName :: T.Text -> ScopedName
+langName = ScopedName namespaceLang . T.toLower
 
-langTag :: ScopedName -> String
+langTag :: ScopedName -> T.Text
 langTag = snLocal
 
 isLang :: ScopedName -> Bool
 --  Define some common vocabulary terms
 ------------------------------------------------------------
 
-toRDF, toRDFS, toRDFD :: String -> ScopedName
+toRDF, toRDFS, toRDFD :: T.Text -> ScopedName
 toRDF  = ScopedName namespaceRDF
 toRDFS = ScopedName namespaceRDFS
 toRDFD = ScopedName namespaceRDFD
 rdfdConstraint         = toRDFD "constraint"
 rdfdMaxCardinality     = toRDFD "maxCardinality"
 
-xsdType             :: String -> ScopedName
+xsdType             :: T.Text -> ScopedName
 xsdType             = ScopedName namespaceXSD
 
 xsdString           :: ScopedName

File Swish/Utils/Namespace.hs

 {-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
 
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  TypeSynonymInstances, MultiParamTypeClasses, FlexibleInstances
+--  Portability :  TypeSynonymInstances, MultiParamTypeClasses, FlexibleInstances, OverloadedStrings
 --
 --  This module defines algebraic datatypes for namespaces and scoped names.
 --
 
 import Network.URI (URI(..), parseURIReference, nullURI)
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as B
 
 ------------------------------------------------------------
 
 data Namespace = Namespace
                  {
-                   nsPrefix :: Maybe String
+                   nsPrefix :: Maybe T.Text
                  , nsURI :: URI
                  }
                  
     (==) = nsEq
 
 instance Show Namespace where
-    show (Namespace (Just p) u) = p ++ ":<" ++ show u ++ ">"
+    show (Namespace (Just p) u) = show p ++ ":<" ++ show u ++ ">"
     show (Namespace _ u)        = "<" ++ show u ++ ">"
 
-instance LookupEntryClass Namespace (Maybe String) URI where
+instance LookupEntryClass Namespace (Maybe T.Text) URI where
     keyVal   (Namespace pre uri) = (pre,uri)
     newEntry (pre,uri)           = Namespace pre uri
 
 nsEq :: Namespace -> Namespace -> Bool
 nsEq (Namespace _ u1) (Namespace _ u2) = u1 == u2
 
-makeNamespaceQName :: Namespace -> String -> QName
+makeNamespaceQName :: Namespace -> T.Text -> QName
 makeNamespaceQName (Namespace _ uri) = newQName uri
 
 {-
 --
 namespaceToBuilder :: Namespace -> B.Builder
 namespaceToBuilder (Namespace pre uri) =
-  mconcat $ map B.fromString 
-  [ "@prefix ", fromMaybe "" pre, ": <", show uri, "> .\n"]
+  mconcat $ map B.fromText 
+  [ "@prefix ", fromMaybe "" pre, ": <", T.pack (show uri), "> .\n"]
 
 ------------------------------------------------------------
 --  ScopedName, made from a namespace and a local name
 --  Some applications may handle null namespace URIs as meaning
 --  the local part is relative to some base URI.
 --
-data ScopedName = ScopedName { snScope :: Namespace, snLocal :: String }
+data ScopedName = ScopedName { snScope :: Namespace, snLocal :: T.Text }
 
-getScopePrefix :: ScopedName -> Maybe String
+getScopePrefix :: ScopedName -> Maybe T.Text
 getScopePrefix = nsPrefix . snScope
 
 getScopeURI :: ScopedName -> URI
 
 instance Show ScopedName where
     show (ScopedName n l) = case nsPrefix n of
-      Just pre -> pre ++ ":" ++ l
-      _        -> "<" ++ show (nsURI n) ++ l ++ ">"
+      Just pre -> T.unpack $ mconcat [pre, ":", l]
+      _        -> "<" ++ show (nsURI n) ++ T.unpack l ++ ">"
 
 --  Scoped names are equal if their corresponding QNames are equal
 snEq :: ScopedName -> ScopedName -> Bool
 getScopedNameURI :: ScopedName -> URI
 getScopedNameURI = getQNameURI . getQName
 
+-- for the moment leave this as String rather than Text
+
 -- |Test if supplied string matches the display form of a
 --  scoped name.
 matchName :: String -> ScopedName -> Bool
 matchName str nam = str == show nam
 
 -- |Construct a ScopedName from prefix, URI and local name
-makeScopedName :: Maybe String -> URI -> String -> ScopedName
+makeScopedName :: Maybe T.Text -> URI -> T.Text -> ScopedName
 makeScopedName pre nsuri =
     ScopedName (Namespace pre nsuri)
 

File Swish/Utils/QName.hs

+{-# LANGUAGE OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  H98
+--  Portability :  OverloadedStrings
 --
 --  This module defines an algebraic datatype for qualified names (QNames).
 --
 import Data.Maybe (fromMaybe)
 -- import Data.List (intercalate)
 
+import qualified Data.Text as T
+
 ------------------------------------------------------------
 --  Qualified name
 ------------------------------------------------------------
 data QName = QName
              { qnURI :: URI       -- ^ URI
              , qnNsuri :: URI     -- ^ namespace 
-             , qnLocal :: String  -- ^ local component
+             , qnLocal :: T.Text  -- ^ local component
              }
 
 instance IsString QName where
             (up2,ur2) = splitAt n u2
   -}
   
+  -- TODO: can we make the following change?
   -- could say (QName u1 _ _) <= QName u2 _ _) = show u1 <= show u2
   (QName _ uri1 l1) <= (QName _ uri2 l2) =
-    if up1 /= up2 then up1 <= up2 else (ur1++l1) <= (ur2++l2)
+    if up1 /= up2 then up1 <= up2 else (ur1 ++ T.unpack l1) <= (ur2 ++ T.unpack l2)
       where
         u1 = show uri1
         u2 = show uri2
 We could also me more clever, and safer, when constructing
 the overall uri.
 -}
-newQName :: URI -> String -> QName
+newQName :: URI -> T.Text -> QName
 newQName ns local = 
-  let uristr = show ns ++ local
-      uri = fromMaybe (error ("Unable to parse URI from: '" ++ show ns ++ "' + '" ++ local ++ "'")) (parseURIReference uristr)
+  let l   = T.unpack local
+      uristr = show ns ++ l
+      uri = fromMaybe (error ("Unable to parse URI from: '" ++ show ns ++ "' + '" ++ l ++ "'")) (parseURIReference uristr)
   in QName uri ns local
 
 {-
       q0 = QName uri uri ""
   in case uf of
     "#"    -> q0
-    '#':xs -> QName uri (uri { uriFragment = "#" }) xs
+    '#':xs -> QName uri (uri { uriFragment = "#" }) (T.pack xs)
     ""     -> case break (=='/') (reverse up) of
       ("",_) -> q0 -- path ends in / or is empty
       (_,"") -> q0 -- path contains no /
-      (rlname,rpath) -> QName uri (uri {uriPath = reverse rpath}) (reverse rlname) 
+      (rlname,rpath) -> QName uri (uri {uriPath = reverse rpath}) (T.pack (reverse rlname))
       
     e -> error $ "Unexpected: uri=" ++ show uri ++ " has fragment='" ++ show e ++ "'" 
 
 getNamespace :: QName -> URI
 getNamespace = qnNsuri
 
-getLocalName :: QName -> String
+getLocalName :: QName -> T.Text
 getLocalName = qnLocal
 
 getQNameURI :: QName -> URI

File tests/BuiltInMapTest.hs

+{-# LANGUAGE OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  H98
+--  Portability :  OverloadedStrings
 --
 --  This module contains test cases for accessing built-in variable
 --  binding modifiers.

File tests/N3FormatterTest.hs

 {-# LANGUAGE OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 
 import Data.String (IsString(..))
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy as L
 import qualified Data.Text.Lazy.Builder as B
 
 toURI :: String -> URI
 toURI = fromJust . parseURI
 
-toNS :: String -> String -> Namespace
+toNS :: T.Text -> String -> Namespace
 toNS p = Namespace (Just p) . toURI
 
-toRes :: Namespace -> String -> RDFLabel
+toRes :: Namespace -> T.Text -> RDFLabel
 toRes ns = Res . ScopedName ns
 
 base1, base2, base3, base4, basef, baseu, basem :: Namespace

File tests/N3ParserTest.hs

 import Data.Monoid (Monoid(..))
 import Data.Maybe (fromMaybe)
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy as L
 import qualified Data.Text.Lazy.Builder as B
 
 dqn :: QName
 dqn = (qnameFromURI . toURI) baseFile
 
-toNS :: String -> String -> Namespace
+toNS :: T.Text -> String -> Namespace
 toNS p = Namespace (Just p) . toURI
 
 dbase, base1, base2, base3, base4, basea :: Namespace
 t06  = arc s3 p1 l2
 t07  = arc s3 p2 l3
 
-makeNewPrefixNamespace :: (String,Namespace) -> Namespace
+makeNewPrefixNamespace :: (T.Text,Namespace) -> Namespace
 makeNewPrefixNamespace (pre,ns) = Namespace (Just pre) (nsURI ns)
 
 dg1, dg2, dg3 :: RDFGraph

File tests/QNameTest.hs

 import Network.URI (URI, parseURIReference)
 import Data.Maybe (fromJust)
 
+import qualified Data.Text as T
+
 ------------------------------------------------------------
 --  Define some common values
 ------------------------------------------------------------
 testStringEq :: String -> String -> String -> Test
 testStringEq = testIsEq "StringEq"
 
+testTextEq :: String -> T.Text -> T.Text -> Test
+testTextEq = testIsEq "TextEq"
+
 testURIEq :: String -> String -> URI -> Test
 testURIEq lbl uri = testIsEq "URIEq" lbl (toURI uri)
 
   , testURIEq "testGetNamespace04"
         "http://id.ninebynine.org/wip/2003/test/graph3/node"
         (getNamespace qb3)
-  , testStringEq "testGetLocalName01"
+  , testTextEq "testGetLocalName01"
         "s1" (getLocalName qb1s1)
-  , testStringEq "testGetLocalName02"
+  , testTextEq "testGetLocalName02"
         "s2" (getLocalName qb2s2)
-  , testStringEq "testGetLocalName03"
+  , testTextEq "testGetLocalName03"
       "s3" (getLocalName qb3s3)
-  , testStringEq "testGetLocalName04"
+  , testTextEq "testGetLocalName04"
       "" (getLocalName qb3)
   , testURIEq "testGetQNameURI01"
       "http://id.ninebynine.org/wip/2003/test/graph1/node#s1"
 URI combination done by newQName (may be tested elsewhere).
 -}
 
-testSplitURI :: String -> String -> (String,String) -> Test
+testSplitURI :: String -> String -> (String,T.Text) -> Test
 testSplitURI lbl input (a,b) =
   let qn = newQName (toURI a) b
   in 

File tests/RDFDatatypeXsdIntegerTest.hs

 toURI :: String -> URI
 toURI = fromJust . parseURI
 
-xsdIntName :: String -> ScopedName
+xsdIntName :: T.Text -> ScopedName
 xsdIntName = ScopedName namespaceXsdInteger 
 
 axiomXsdIntegerDT :: ScopedName

File tests/RDFGraphTest.hs

 toURI :: String -> URI
 toURI s = fromMaybe (error $ "Error: unable to parse URI " ++ s) (parseURI s)
 
-toNS :: String -> String -> Namespace
+toNS :: T.Text -> String -> Namespace
 toNS p = Namespace (Just p) . toURI
 
 -- TODO: basee and baseu had prefixes of "" and "?" before the conversion
 tt05 = arc st2 p1 l4
 tt06 = arc st3 p1 l10
 
-makeNewPrefixNamespace :: (String,Namespace) -> Namespace
+makeNewPrefixNamespace :: (T.Text,Namespace) -> Namespace
 makeNewPrefixNamespace (pre,ns) = Namespace (Just pre) (nsURI ns)
 
 nslist :: LookupMap Namespace

File tests/RDFProofContextTest.hs

 import Data.Monoid (Monoid(..))
 import Data.Maybe (isJust, isNothing, fromJust, fromMaybe)
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as B
 
 --  misc helpers
 
 --  Various support methods
 
-makeFormula :: Namespace -> String -> B.Builder -> RDFFormula
+makeFormula :: Namespace -> T.Text -> B.Builder -> RDFFormula
 makeFormula scope local gr =
     makeRDFFormula scope local (prefix `mappend` gr)
 
 getAxiom nam = getContextAxiom (makeSName nam) nullRDFFormula rdfdContext
 
 makeSName :: String -> ScopedName
-makeSName nam = ScopedName ns loc
+makeSName nam = ScopedName ns (T.pack loc)
     where
         (pre,_:loc) = break (==':') nam
         ns = case pre of
 toURI :: String -> URI
 toURI = fromJust . parseURI
 
-toNS :: Maybe String -> String -> Namespace
+toNS :: Maybe T.Text -> String -> Namespace
 toNS p = Namespace p . toURI
 
 mkPrefix :: Namespace -> B.Builder

File tests/RDFProofTest.hs

 import Data.Monoid (Monoid(..))
 import Data.Maybe (isJust, fromJust)
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as B
 
 --  misc helpers
 toURI :: String -> URI
 toURI = fromJust . parseURI
 
-toNS :: Maybe String -> String -> Namespace
+toNS :: Maybe T.Text -> String -> Namespace
 toNS p = Namespace p . toURI
 
 --  test1:  simple query with URI, literal and blank nodes.

File tests/RDFRulesetTest.hs

 import Data.List (nub, sort)
 import Data.Maybe (isJust, fromJust)
 
+import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as B
 
 ------------------------------------------------------------
 toURI :: String -> URI
 toURI = fromJust . parseURI
 
-toNS :: Maybe String -> String -> Namespace
+toNS :: Maybe T.Text -> String -> Namespace
 toNS p = Namespace p . toURI
 
 ------------------------------------------------------------
 scopeex :: Namespace
 scopeex = toNS (Just "ex") "http://id.ninebynine.org/wip/2003/RDFProofCheck#"
 
-makeFormula :: Namespace -> String -> B.Builder -> RDFFormula
+makeFormula :: Namespace -> T.Text -> B.Builder -> RDFFormula
 makeFormula scope local gr =
     makeRDFFormula scope local $ prefix `mappend` gr
 

File tests/VarBindingTest.hs

+{-# LANGUAGE OverloadedStrings #-}
+
 --------------------------------------------------------------------------------
 --  See end of this file for licence information.
 --------------------------------------------------------------------------------
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  H98
+--  Portability :  OverloadedStrings
 --
 --  This module contains test cases for variable binding values and
 --  variable binding modifier values.
 import Data.List (union, intersect)
 import Data.Maybe (isJust, isNothing, fromJust)
 
+-- import qualified Data.Text as T
+
 ------------------------------------------------------------
 --  Test case helpers
 ------------------------------------------------------------